From b1352010c4a9464d4e5716c314e817ec4f8bb155 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 28 Mar 2025 11:03:55 +0100 Subject: [PATCH 01/40] NTP: discard corrupted NTP response --- src/utility/time/NTPUtils.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/utility/time/NTPUtils.cpp b/src/utility/time/NTPUtils.cpp index 24c626a73..ae0a482c8 100644 --- a/src/utility/time/NTPUtils.cpp +++ b/src/utility/time/NTPUtils.cpp @@ -62,6 +62,12 @@ unsigned long NTPUtils::getTime(UDP & udp) unsigned long const highWord = word(ntp_packet_buf[40], ntp_packet_buf[41]); unsigned long const lowWord = word(ntp_packet_buf[42], ntp_packet_buf[43]); unsigned long const secsSince1900 = highWord << 16 | lowWord; + + /* Check for corrupted NTP response */ + if(secsSince1900 == 0) { + return 0; + } + unsigned long const seventyYears = 2208988800UL; unsigned long const epoch = secsSince1900 - seventyYears; From f6f4468202c84c546c7f0a8d49d8a39d658f3aa2 Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 28 Mar 2025 11:04:13 +0100 Subject: [PATCH 02/40] NTP: remove spaces --- src/utility/time/NTPUtils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utility/time/NTPUtils.cpp b/src/utility/time/NTPUtils.cpp index ae0a482c8..3069ae823 100644 --- a/src/utility/time/NTPUtils.cpp +++ b/src/utility/time/NTPUtils.cpp @@ -54,7 +54,7 @@ unsigned long NTPUtils::getTime(UDP & udp) udp.stop(); return 0; } - + uint8_t ntp_packet_buf[NTP_PACKET_SIZE]; udp.read(ntp_packet_buf, NTP_PACKET_SIZE); udp.stop(); @@ -81,7 +81,7 @@ unsigned long NTPUtils::getTime(UDP & udp) void NTPUtils::sendNTPpacket(UDP & udp) { uint8_t ntp_packet_buf[NTP_PACKET_SIZE] = {0}; - + ntp_packet_buf[0] = 0b11100011; ntp_packet_buf[1] = 0; ntp_packet_buf[2] = 6; @@ -90,7 +90,7 @@ void NTPUtils::sendNTPpacket(UDP & udp) ntp_packet_buf[13] = 0x4E; ntp_packet_buf[14] = 49; ntp_packet_buf[15] = 52; - + udp.beginPacket(NTP_TIME_SERVER, NTP_TIME_SERVER_PORT); udp.write(ntp_packet_buf, NTP_PACKET_SIZE); udp.endPacket(); From c408cc07ffb94ae7b79700385c36f9e96d980b67 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 2 Apr 2025 15:15:13 +0200 Subject: [PATCH 03/40] raising minimum cmake version number as 2.8 is deprecated --- extras/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index e71791f66..7ab5f1f5c 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -1,6 +1,6 @@ ########################################################################## -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) ########################################################################## From 03d1d627ef1a05294cd40dcc45c370811844fe88 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 10:41:07 +0100 Subject: [PATCH 04/40] added CMake into gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 52218a217..c71e1ae86 100644 --- a/.gitignore +++ b/.gitignore @@ -20,5 +20,7 @@ CTestTestfile.cmake _deps ### CMake Patch ### +CMakeUserPresets.json + # External projects *-prefix/ From 697cd611fe190b069c61f046a5ec39b49852e864 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Nov 2024 12:14:14 +0100 Subject: [PATCH 05/40] Use Arduino_CloudUtils --- src/ota/implementation/OTAUnoR4.cpp | 1 - src/ota/interface/OTAInterface.h | 2 +- src/ota/interface/OTAInterfaceDefault.cpp | 56 +------- src/ota/interface/OTAInterfaceDefault.h | 4 +- src/tls/utility/SHA256.cpp | 47 ------- src/tls/utility/SHA256.h | 48 ------- src/utility/lzss/lzss.cpp | 163 ---------------------- src/utility/lzss/lzss.h | 108 -------------- 8 files changed, 8 insertions(+), 421 deletions(-) delete mode 100644 src/tls/utility/SHA256.cpp delete mode 100644 src/tls/utility/SHA256.h delete mode 100644 src/utility/lzss/lzss.cpp delete mode 100644 src/utility/lzss/lzss.h diff --git a/src/ota/implementation/OTAUnoR4.cpp b/src/ota/implementation/OTAUnoR4.cpp index 5d9cffee8..5ba12afa9 100644 --- a/src/ota/implementation/OTAUnoR4.cpp +++ b/src/ota/implementation/OTAUnoR4.cpp @@ -14,7 +14,6 @@ #include "OTAUnoR4.h" #include -#include "tls/utility/SHA256.h" #include "fsp_common_api.h" #include "r_flash_lp.h" #include "WiFi.h" diff --git a/src/ota/interface/OTAInterface.h b/src/ota/interface/OTAInterface.h index d9624c3ba..d3d21f0f1 100644 --- a/src/ota/interface/OTAInterface.h +++ b/src/ota/interface/OTAInterface.h @@ -18,7 +18,7 @@ #if OTA_ENABLED #include "../OTATypes.h" -#include "tls/utility/SHA256.h" +#include #include #include diff --git a/src/ota/interface/OTAInterfaceDefault.cpp b/src/ota/interface/OTAInterfaceDefault.cpp index a641595b6..fbea43e68 100644 --- a/src/ota/interface/OTAInterfaceDefault.cpp +++ b/src/ota/interface/OTAInterfaceDefault.cpp @@ -10,6 +10,7 @@ #include #if OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) +#include #include "OTAInterfaceDefault.h" #include "../OTA.h" @@ -119,7 +120,7 @@ OTACloudProcessInterface::State OTADefaultCloudProcessInterface::fetch() { // this could distinguish between consistency of the downloaded bytes and filesize // validate CRC - context->calculatedCrc32 ^= 0xFFFFFFFF; // finalize CRC + context->calculatedCrc32 = arduino::crc32::finalize(context->calculatedCrc32); if(context->header.header.crc32 == context->calculatedCrc32) { DEBUG_VERBOSE("Ota download completed successfully"); res = FlashOTA; @@ -215,7 +216,7 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t bufLen) { if(sizeof(context->header.buf) == context->headerCopiedBytes) { context->downloadState = OtaDownloadFile; - context->calculatedCrc32 = crc_update( + context->calculatedCrc32 = arduino::crc32::update( context->calculatedCrc32, &(context->header.header.magic_number), sizeof(context->header) - offsetof(ota::OTAHeader, header.magic_number) @@ -234,7 +235,7 @@ void OTADefaultCloudProcessInterface::parseOta(uint8_t* buffer, size_t bufLen) { const uint32_t dataLeft = bufLen - (cursor-buffer); context->decoder.decompress(cursor, dataLeft); // TODO verify return value - context->calculatedCrc32 = crc_update( + context->calculatedCrc32 = arduino::crc32::update( context->calculatedCrc32, cursor, dataLeft @@ -292,7 +293,7 @@ OTADefaultCloudProcessInterface::Context::Context( const char* url, std::function putc) : parsed_url(url) , downloadState(OtaDownloadHeader) - , calculatedCrc32(0xFFFFFFFF) + , calculatedCrc32(arduino::crc32::begin()) , headerCopiedBytes(0) , downloadedSize(0) , lastReportTime(0) @@ -301,51 +302,4 @@ OTADefaultCloudProcessInterface::Context::Context( , downloadedChunkSize(0) , decoder(putc) { } -static const uint32_t crc_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t crc_update(uint32_t crc, const void * data, size_t data_len) { - const unsigned char *d = (const unsigned char *)data; - unsigned int tbl_idx; - - while (data_len--) { - tbl_idx = (crc ^ *d) & 0xff; - crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; - d++; - } - - return crc & 0xffffffff; -} #endif /* OTA_ENABLED && ! defined(OFFLOADED_DOWNLOAD) */ diff --git a/src/ota/interface/OTAInterfaceDefault.h b/src/ota/interface/OTAInterfaceDefault.h index b45c14dd6..581a6bc54 100644 --- a/src/ota/interface/OTAInterfaceDefault.h +++ b/src/ota/interface/OTAInterfaceDefault.h @@ -16,7 +16,7 @@ #include #include -#include "utility/lzss/lzss.h" +#include #include "OTAInterface.h" /** @@ -87,7 +87,7 @@ class OTADefaultCloudProcessInterface: public OTACloudProcessInterface { uint32_t downloadedChunkSize; // LZSS decoder - LZSSDecoder decoder; + arduino::lzss::Decoder decoder; static constexpr size_t bufLen = 64; uint8_t buffer[bufLen]; diff --git a/src/tls/utility/SHA256.cpp b/src/tls/utility/SHA256.cpp deleted file mode 100644 index ffed6e587..000000000 --- a/src/tls/utility/SHA256.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2020 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "SHA256.h" - -/****************************************************************************** - * STATIC MEMBER DECLARATION - ******************************************************************************/ - -constexpr size_t SHA256::HASH_SIZE; - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -void SHA256::begin() -{ - br_sha256_init(&_ctx); -} - -void SHA256::update(uint8_t const * data, size_t const len) -{ - br_sha256_update(&_ctx, data, len); -} - -void SHA256::finalize(uint8_t * hash) -{ - br_sha256_out(&_ctx, hash); -} diff --git a/src/tls/utility/SHA256.h b/src/tls/utility/SHA256.h deleted file mode 100644 index ed0ce1d5a..000000000 --- a/src/tls/utility/SHA256.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This file is part of ArduinoIoTCloud. - - Copyright 2020 ARDUINO SA (http://www.arduino.cc/) - - This software is released under the GNU General Public License version 3, - which covers the main part of arduino-cli. - The terms of this license can be found at: - https://www.gnu.org/licenses/gpl-3.0.en.html - - You can be released from the requirements of the above licenses by purchasing - a commercial license. Buying such a license is mandatory if you want to modify or - otherwise use the software for commercial activities involving the Arduino - software without disclosing the source code of your own applications. To purchase - a commercial license, send an email to license@arduino.cc. -*/ - -#ifndef ARDUINO_TLS_UTILITY_SHA256_H_ -#define ARDUINO_TLS_UTILITY_SHA256_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "../bearssl/bearssl_hash.h" - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class SHA256 -{ - -public: - - static constexpr size_t HASH_SIZE = 32; - - void begin (); - void update (uint8_t const * data, size_t const len); - void finalize(uint8_t * hash); - -private: - - br_sha256_context _ctx; - -}; - -#endif /* ARDUINO_TLS_UTILITY_SHA256_H_ */ diff --git a/src/utility/lzss/lzss.cpp b/src/utility/lzss/lzss.cpp deleted file mode 100644 index 1a11399f6..000000000 --- a/src/utility/lzss/lzss.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - - This implementation took inspiration from https://okumuralab.org/~okumura/compression/lzss.c source code -*/ - -/************************************************************************************** - INCLUDE - **************************************************************************************/ -#include "lzss.h" - -#include - -/************************************************************************************** - LZSS DECODER CLASS IMPLEMENTATION - **************************************************************************************/ - -// get the number of bits the algorithm will try to get given the state -uint8_t LZSSDecoder::bits_required(LZSSDecoder::FSM_STATES s) { - switch(s) { - case FSM_0: - return 1; - case FSM_1: - return 8; - case FSM_2: - return EI; - case FSM_3: - return EJ; - default: - return 0; - } -} - -LZSSDecoder::LZSSDecoder(std::function getc_cbk, std::function putc_cbk) -: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(getc_cbk) { - for (int i = 0; i < N - F; i++) buffer[i] = ' '; - r = N - F; -} - - -LZSSDecoder::LZSSDecoder(std::function putc_cbk) -: available(0), state(FSM_0), put_char_cbk(putc_cbk), get_char_cbk(nullptr) { - for (int i = 0; i < N - F; i++) buffer[i] = ' '; - r = N - F; -} - -LZSSDecoder::status LZSSDecoder::handle_state() { - LZSSDecoder::status res = IN_PROGRESS; - - int c = getbit(bits_required(this->state)); - - if(c == LZSS_BUFFER_EMPTY) { - res = NOT_COMPLETED; - } else if (c == LZSS_EOF) { - res = DONE; - this->state = FSM_EOF; - } else { - switch(this->state) { - case FSM_0: - if(c) { - this->state = FSM_1; - } else { - this->state = FSM_2; - } - break; - case FSM_1: - putc(c); - buffer[r++] = c; - r &= (N - 1); // equivalent to r = r % N when N is a power of 2 - - this->state = FSM_0; - break; - case FSM_2: - this->i = c; - this->state = FSM_3; - break; - case FSM_3: { - int j = c; - - // This is where the actual decompression takes place: we look into the local buffer for reuse - // of byte chunks. This can be improved by means of memcpy and by changing the putc function - // into a put_buf function in order to avoid buffering on the other end. - // TODO improve this section of code - for (int k = 0; k <= j + 1; k++) { - c = buffer[(this->i + k) & (N - 1)]; // equivalent to buffer[(i+k) % N] when N is a power of 2 - putc(c); - buffer[r++] = c; - r &= (N - 1); // equivalent to r = r % N - } - this->state = FSM_0; - - break; - } - case FSM_EOF: - break; - } - } - - return res; -} - -LZSSDecoder::status LZSSDecoder::decompress(uint8_t* const buffer, uint32_t size) { - if(!get_char_cbk) { - this->in_buffer = buffer; - this->available += size; - } - - status res = IN_PROGRESS; - - while((res = handle_state()) == IN_PROGRESS); - - this->in_buffer = nullptr; - - return res; -} - -int LZSSDecoder::getbit(uint8_t n) { // get n bits from buffer - int x=0, c; - - // if the local bit buffer doesn't have enough bit get them - while(buf_size < n) { - switch(c=getc()) { - case LZSS_EOF: - case LZSS_BUFFER_EMPTY: - return c; - } - buf <<= 8; - - buf |= (uint8_t)c; - buf_size += sizeof(uint8_t)*8; - } - - // the result is the content of the buffer starting from msb to n successive bits - x = buf >> (buf_size-n); - - // remove from the buffer the read bits with a mask - buf &= (1<<(buf_size-n))-1; - - buf_size-=n; - - return x; -} - -int LZSSDecoder::getc() { - int c; - - if(get_char_cbk) { - c = get_char_cbk(); - } else if(in_buffer == nullptr || available == 0) { - c = LZSS_BUFFER_EMPTY; - } else { - c = *in_buffer; - in_buffer++; - available--; - } - return c; -} \ No newline at end of file diff --git a/src/utility/lzss/lzss.h b/src/utility/lzss/lzss.h deleted file mode 100644 index bf652026e..000000000 --- a/src/utility/lzss/lzss.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#pragma once - -/************************************************************************************** - INCLUDE - **************************************************************************************/ -#include -#include -#include - -/************************************************************************************** - FUNCTION DEFINITION - **************************************************************************************/ - -/************************************************************************************** - LZSS DECODER CLASS - **************************************************************************************/ - - -class LZSSDecoder { -public: - - /** - * Build an LZSS decoder by providing a callback for storing the decoded bytes - * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite - */ - LZSSDecoder(std::function putc_cbk); - - /** - * Build an LZSS decoder providing a callback for getting a char and putting a char - * in this way you need to call decompress with no parameters - * @param putc_cbk: a callback that takes a char and stores it e.g. a callback to fwrite - * @param getc_cbk: a callback that returns the next char to consume - * -1 means EOF, -2 means buffer is temporairly finished - */ - LZSSDecoder(std::function getc_cbk, std::function putc_cbk); - - /** - * this enum describes the result of the computation of a single FSM computation - * DONE: the decompression is completed - * IN_PROGRESS: the decompression cycle completed successfully, ready to compute next - * NOT_COMPLETED: the current cycle didn't complete because the available data is not enough - */ - enum status: uint8_t { - DONE, - IN_PROGRESS, - NOT_COMPLETED - }; - - /** - * decode the provided buffer until buffer ends, then pause the process - * @return DONE if the decompression is completed, NOT_COMPLETED if not - */ - status decompress(uint8_t* const buffer=nullptr, uint32_t size=0); - - static const int LZSS_EOF = -1; - static const int LZSS_BUFFER_EMPTY = -2; -private: - // TODO provide a way for the user to set these parameters - static const int EI = 11; /* typically 10..13 */ - static const int EJ = 4; /* typically 4..5 */ - static const int N = (1 << EI); /* buffer size */ - static const int F = ((1 << EJ) + 1); /* lookahead buffer size */ - - // algorithm specific buffer used to store text that could be later referenced and copied - uint8_t buffer[N * 2]; - - // this function gets 1 single char from the input buffer - int getc(); - uint8_t* in_buffer = nullptr; - uint32_t available = 0; - - status handle_state(); - - // get 1 bit from the available input buffer - int getbit(uint8_t n); - // the following 2 are variables used by getbits - uint32_t buf, buf_size=0; - - enum FSM_STATES: uint8_t { - FSM_0 = 0, - FSM_1 = 1, - FSM_2 = 2, - FSM_3 = 3, - FSM_EOF - } state; - - // these variable are used in a decode session and specific to the old C implementation - // there is no documentation about their meaning - int i, r; - - std::function put_char_cbk; - std::function get_char_cbk; - - inline void putc(const uint8_t c) { if(put_char_cbk) { put_char_cbk(c); } } - - // get the number of bits the FSM will require given its state - uint8_t bits_required(FSM_STATES s); -}; \ No newline at end of file From 2894f3765b972572e4abcbb625c8a686ec35d0ff Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 20 Nov 2024 12:14:14 +0100 Subject: [PATCH 06/40] offload tinycbor to CloudUtils --- src/cbor/CBOREncoder.cpp | 2 +- src/cbor/MessageDecoder.h | 2 +- src/cbor/MessageEncoder.cpp | 1 - src/cbor/MessageEncoder.h | 2 +- src/cbor/lib/tinycbor/cbor-lib.h | 36 - src/cbor/lib/tinycbor/src/cbor.dox | 123 -- src/cbor/lib/tinycbor/src/cbor.h | 639 -------- src/cbor/lib/tinycbor/src/cborencoder.c | 650 -------- .../src/cborencoder_close_container_checked.c | 62 - src/cbor/lib/tinycbor/src/cborerrorstrings.c | 190 --- src/cbor/lib/tinycbor/src/cborinternal_p.h | 161 -- src/cbor/lib/tinycbor/src/cborjson.h | 62 - src/cbor/lib/tinycbor/src/cborparser.c | 1435 ----------------- .../lib/tinycbor/src/cborparser_dup_string.c | 124 -- src/cbor/lib/tinycbor/src/cborpretty.c | 583 ------- src/cbor/lib/tinycbor/src/cborpretty_stdio.c | 91 -- src/cbor/lib/tinycbor/src/cbortojson.c | 704 -------- src/cbor/lib/tinycbor/src/cborvalidation.c | 671 -------- src/cbor/lib/tinycbor/src/compilersupport_p.h | 205 --- src/cbor/lib/tinycbor/src/open_memstream.c | 112 -- src/cbor/lib/tinycbor/src/tags.txt | 23 - src/cbor/lib/tinycbor/src/tinycbor-version.h | 3 - src/cbor/lib/tinycbor/src/utf8_p.h | 104 -- src/property/Property.h | 2 +- 24 files changed, 4 insertions(+), 5983 deletions(-) delete mode 100644 src/cbor/lib/tinycbor/cbor-lib.h delete mode 100644 src/cbor/lib/tinycbor/src/cbor.dox delete mode 100644 src/cbor/lib/tinycbor/src/cbor.h delete mode 100644 src/cbor/lib/tinycbor/src/cborencoder.c delete mode 100644 src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c delete mode 100644 src/cbor/lib/tinycbor/src/cborerrorstrings.c delete mode 100644 src/cbor/lib/tinycbor/src/cborinternal_p.h delete mode 100644 src/cbor/lib/tinycbor/src/cborjson.h delete mode 100644 src/cbor/lib/tinycbor/src/cborparser.c delete mode 100644 src/cbor/lib/tinycbor/src/cborparser_dup_string.c delete mode 100644 src/cbor/lib/tinycbor/src/cborpretty.c delete mode 100644 src/cbor/lib/tinycbor/src/cborpretty_stdio.c delete mode 100644 src/cbor/lib/tinycbor/src/cbortojson.c delete mode 100644 src/cbor/lib/tinycbor/src/cborvalidation.c delete mode 100644 src/cbor/lib/tinycbor/src/compilersupport_p.h delete mode 100644 src/cbor/lib/tinycbor/src/open_memstream.c delete mode 100644 src/cbor/lib/tinycbor/src/tags.txt delete mode 100644 src/cbor/lib/tinycbor/src/tinycbor-version.h delete mode 100644 src/cbor/lib/tinycbor/src/utf8_p.h diff --git a/src/cbor/CBOREncoder.cpp b/src/cbor/CBOREncoder.cpp index d166756d4..74106cde7 100644 --- a/src/cbor/CBOREncoder.cpp +++ b/src/cbor/CBOREncoder.cpp @@ -26,7 +26,7 @@ #include #include -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** * PUBLIC MEMBER FUNCTIONS diff --git a/src/cbor/MessageDecoder.h b/src/cbor/MessageDecoder.h index 1223e947b..2ade0eaf7 100644 --- a/src/cbor/MessageDecoder.h +++ b/src/cbor/MessageDecoder.h @@ -23,7 +23,7 @@ #include "CBOR.h" #include "../interfaces/Decoder.h" -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** CLASS DECLARATION diff --git a/src/cbor/MessageEncoder.cpp b/src/cbor/MessageEncoder.cpp index cdeb0f8ed..56bae9ef2 100644 --- a/src/cbor/MessageEncoder.cpp +++ b/src/cbor/MessageEncoder.cpp @@ -19,7 +19,6 @@ #include #include -#include "lib/tinycbor/cbor-lib.h" #include "MessageEncoder.h" /****************************************************************************** diff --git a/src/cbor/MessageEncoder.h b/src/cbor/MessageEncoder.h index 86792eb19..81ae94ce8 100644 --- a/src/cbor/MessageEncoder.h +++ b/src/cbor/MessageEncoder.h @@ -23,7 +23,7 @@ #include "CBOR.h" #include "../interfaces/Encoder.h" -#include "lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** * CLASS DECLARATION diff --git a/src/cbor/lib/tinycbor/cbor-lib.h b/src/cbor/lib/tinycbor/cbor-lib.h deleted file mode 100644 index e8d8004e7..000000000 --- a/src/cbor/lib/tinycbor/cbor-lib.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef CBOR_LIB_H -#define CBOR_LIB_H - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include "src/cbor.h" - -/****************************************************************************** - * DEFINE - ******************************************************************************/ - -#ifndef CHECK_CBOR - #define CHECK_CBOR(expr) \ - do { \ - CborError error = CborNoError; \ - error = (expr); \ - if (CborNoError != error) \ - return error; \ - } while(0); -#endif /* CHECK_CBOR */ - -#ifndef CHECK_CBOR_MULTI - #define CHECK_CBOR_MULTI(expr) \ - do { \ - CborError error = CborNoError; \ - error = (expr); \ - if (CborErrorOutOfMemory == error) \ - return CborErrorSplitItems; \ - if (CborNoError != error) \ - return error; \ - } while(0); -#endif /* CHECK_CBOR_MULTI */ - -#endif \ No newline at end of file diff --git a/src/cbor/lib/tinycbor/src/cbor.dox b/src/cbor/lib/tinycbor/src/cbor.dox deleted file mode 100644 index 0bf5c54c2..000000000 --- a/src/cbor/lib/tinycbor/src/cbor.dox +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -/** - * \mainpage - * The TinyCBOR $(VERSION) library is a small CBOR encoder and decoder library, - * optimized for very fast operation with very small footprint. The main encoder - * and decoder functions do not allocate memory. - * - * TinyCBOR is divided into the following groups of functions and structures: - * - \ref CborGlobals - * - \ref CborEncoding - * - \ref CborParsing - * - \ref CborPretty - * - \ref CborToJson - */ - -/** - * \file - * The is the main header in TinyCBOR and defines the constants used by most functions - * as well as the structures for encoding (CborEncoder) and decoding (CborValue). - * - * \sa - */ - -/** - * \file - * The file contains the routines that are used to convert a CBOR - * data stream into JSON. - * - * \sa - */ - -/** - * \defgroup CborGlobals Global constants - * \brief Constants used by all TinyCBOR function groups. - */ - -/** - * \addtogroup CborGlobals - * @{ - */ - -/** - * \var size_t CborIndefiniteLength - * - * This variable is a constant used to indicate that the length of the map or - * array is not yet determined. It is used in functions - * cbor_encoder_create_map() and cbor_encoder_create_array() - */ - -/** - * \enum CborType - * The CborType enum contains the types known to TinyCBOR. - * - * \value CborIntegerType Type is an integer value, positive, negative or zero - * \value CborByteStringType Type is a string of arbitrary raw bytes - * \value CborTextStringType Type is a text string encoded in UTF-8 - * \value CborArrayType Type is a CBOR array - * \value CborMapType Type is a CBOR map (an associative container with key and value pairs) - * \value CborTagType Type is a CBOR tag (a 64-bit integer describing the item that follows, see CborKnownTags) - * \value CborSimpleType Type is one of the CBOR Simple Types - * \value CborBooleanType Type is a boolean (true or false) - * \value CborNullType Type encodes a null - * \value CborUndefinedType Type encodes an undefined value - * \value CborHalfFloatType Type is an IEEE 754 half precision (16-bit) floating point type - * \value CborFloatType Type is an IEEE 754 single precision (32-bit) floating point type - * \value CborDoubleType Type is an IEEE 754 double precision (64-bit) floating point type - * \value CborInvalidType Type is not valid (this value is used to indicate error conditions) - */ - -/** - * \enum CborKnownTags - * The CborKnownTags enum contains known tags specified in RFC 7049, for use by the application. - * TinyCBOR does not usually interpret the meaning of these tags and does not add them to the - * output stream, unless specifically instructed to do so in functions for that effect. - * - * \value CborDateTimeStringTag Text string contains a date-time encoded in RFC 3339 format, "YYYY-MM-DD hh:mm:ss+zzzz" - * \value CborUnixTime_tTag Number is a Unix time_t quantity, the number of seconds since 1970-01-01 midnight UTC - * \value CborPositiveBignumTag Item is a CBOR byte string encoding a positive integer of arbitrary precision - * \value CborNegativeBignumTag Item is a CBOR byte string encoding a negative integer of arbitrary precision - * \value CborDecimalTag Item is a CBOR array of two integers encoding a fixed-point decimal - * \value CborBigfloatTag Item is a bigfloat - * \value CborExpectedBase64urlTag Item is a CBOR byte string that is expected to be encoded as Base64Url - * \value CborExpectedBase64Tag Item is a CBOR byte string that is expected to be encoded as Base64 - * \value CborExpectedBase16Tag Item is a CBOR byte string that is expected to be encoded as Base16 (also known as "hexdump") - * \value CborUriTag Item is a CBOR text string containing a URI (RFC 3986) or IRI (RFC 3987) - * \value CborBase64urlTag Item is a CBOR text string that was encoded as Base64Url - * \value CborBase64Tag Item is a CBOR text string that was encoded as Base64 - * \value CborRegularExpressionTag Item is a CBOR text string containing a regular expression - * \value CborMimeMessageTag Item is a CBOR text string containing a MIME message (RFC 2045, 2046, 2047, 2822) - * \value CborSignatureTag Item contains CBOR-encoded data. - * This tag is also used as "file magic," marking a file as containing CBOR - */ - -/** - * \typedef CborTag - * This typedef is an unsigned 64-bit integer. Known CBOR tags can be used from the CborKnownTags enum - * but the user application may use other tag values than the ones specified in RFC 7049. - */ - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cbor.h b/src/cbor/lib/tinycbor/src/cbor.h deleted file mode 100644 index 27a4fe4a8..000000000 --- a/src/cbor/lib/tinycbor/src/cbor.h +++ /dev/null @@ -1,639 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBOR_H -#define CBOR_H - -#ifndef assert -#include -#endif -#include -#include -#include -#include -#include - -#include "tinycbor-version.h" - -#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH) - -#ifdef __cplusplus -extern "C" { -#else -#include -#endif - -#ifndef SIZE_MAX -/* Some systems fail to define SIZE_MAX in , even though C99 requires it... - * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2, - * which says: "the value is converted by repeatedly adding or subtracting one more than the - * maximum value that can be represented in the new type until the value is in the range of the - * new type." - * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX. - */ -# define SIZE_MAX ((size_t)-1) -#endif - -#ifndef CBOR_API -# define CBOR_API -#endif -#ifndef CBOR_PRIVATE_API -# define CBOR_PRIVATE_API -#endif -#ifndef CBOR_INLINE_API -# if defined(__cplusplus) -# define CBOR_INLINE inline -# define CBOR_INLINE_API inline -# else -# define CBOR_INLINE_API static CBOR_INLINE -# if defined(_MSC_VER) -# define CBOR_INLINE __inline -# elif defined(__GNUC__) -# define CBOR_INLINE __inline__ -# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define CBOR_INLINE inline -# else -# define CBOR_INLINE -# endif -# endif -#endif - -typedef enum CborType { - CborIntegerType = 0x00, - CborByteStringType = 0x40, - CborTextStringType = 0x60, - CborArrayType = 0x80, - CborMapType = 0xa0, - CborTagType = 0xc0, - CborSimpleType = 0xe0, - CborBooleanType = 0xf5, - CborNullType = 0xf6, - CborUndefinedType = 0xf7, - CborHalfFloatType = 0xf9, - CborFloatType = 0xfa, - CborDoubleType = 0xfb, - - CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */ -} CborType; - -typedef uint64_t CborTag; -typedef enum CborKnownTags { - CborDateTimeStringTag = 0, - CborUnixTime_tTag = 1, - CborPositiveBignumTag = 2, - CborNegativeBignumTag = 3, - CborDecimalTag = 4, - CborBigfloatTag = 5, - CborCOSE_Encrypt0Tag = 16, - CborCOSE_Mac0Tag = 17, - CborCOSE_Sign1Tag = 18, - CborExpectedBase64urlTag = 21, - CborExpectedBase64Tag = 22, - CborExpectedBase16Tag = 23, - CborEncodedCborTag = 24, - CborUrlTag = 32, - CborBase64urlTag = 33, - CborBase64Tag = 34, - CborRegularExpressionTag = 35, - CborMimeMessageTag = 36, - CborCOSE_EncryptTag = 96, - CborCOSE_MacTag = 97, - CborCOSE_SignTag = 98, - CborSignatureTag = 55799 -} CborKnownTags; - -/* #define the constants so we can check with #ifdef */ -#define CborDateTimeStringTag CborDateTimeStringTag -#define CborUnixTime_tTag CborUnixTime_tTag -#define CborPositiveBignumTag CborPositiveBignumTag -#define CborNegativeBignumTag CborNegativeBignumTag -#define CborDecimalTag CborDecimalTag -#define CborBigfloatTag CborBigfloatTag -#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag -#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag -#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag -#define CborExpectedBase64urlTag CborExpectedBase64urlTag -#define CborExpectedBase64Tag CborExpectedBase64Tag -#define CborExpectedBase16Tag CborExpectedBase16Tag -#define CborEncodedCborTag CborEncodedCborTag -#define CborUrlTag CborUrlTag -#define CborBase64urlTag CborBase64urlTag -#define CborBase64Tag CborBase64Tag -#define CborRegularExpressionTag CborRegularExpressionTag -#define CborMimeMessageTag CborMimeMessageTag -#define CborCOSE_EncryptTag CborCOSE_EncryptTag -#define CborCOSE_MacTag CborCOSE_MacTag -#define CborCOSE_SignTag CborCOSE_SignTag -#define CborSignatureTag CborSignatureTag - -/* Error API */ - -typedef enum CborError { - CborNoError = 0, - - /* errors in all modes */ - CborUnknownError, - CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */ - CborErrorAdvancePastEOF, - CborErrorIO, - - /* parser errors streaming errors */ - CborErrorGarbageAtEnd = 256, - CborErrorUnexpectedEOF, - CborErrorUnexpectedBreak, - CborErrorUnknownType, /* can only happen in major type 7 */ - CborErrorIllegalType, /* type not allowed here */ - CborErrorIllegalNumber, - CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */ - - /* parser errors in strict mode parsing only */ - CborErrorUnknownSimpleType = 512, - CborErrorUnknownTag, - CborErrorInappropriateTagForType, - CborErrorDuplicateObjectKeys, - CborErrorInvalidUtf8TextString, - CborErrorExcludedType, - CborErrorExcludedValue, - CborErrorImproperValue, - CborErrorOverlongEncoding, - CborErrorMapKeyNotString, - CborErrorMapNotSorted, - CborErrorMapKeysNotUnique, - - /* encoder errors */ - CborErrorTooManyItems = 768, - CborErrorTooFewItems, - CborErrorSplitItems, - - /* internal implementation errors */ - CborErrorDataTooLarge = 1024, - CborErrorNestingTooDeep, - CborErrorUnsupportedType, - - /* errors in converting to JSON */ - CborErrorJsonObjectKeyIsAggregate = 1280, - CborErrorJsonObjectKeyNotString, - CborErrorJsonNotImplemented, - - CborErrorOutOfMemory = (int) (~0U / 2 + 1), - CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */ -} CborError; - -CBOR_API const char *cbor_error_string(CborError error); - -/* Encoder API */ -struct CborEncoder -{ - union { - uint8_t *ptr; - ptrdiff_t bytes_needed; - } data; - const uint8_t *end; - size_t remaining; - int flags; -}; -typedef struct CborEncoder CborEncoder; - -static const size_t CborIndefiniteLength = SIZE_MAX; - -CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags); -CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value); -CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value); -CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value); -CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value); -CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag); -CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length); -CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) -{ return cbor_encode_text_string(encoder, string, strlen(string)); } -CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length); -CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value); - -CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value) -{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); } -CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); } -CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder) -{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); } - -CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) -{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); } -CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value) -{ return cbor_encode_floating_point(encoder, CborFloatType, &value); } -CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value) -{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); } - -CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length); -CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length); -CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder); -CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder); - -CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder) -{ - return encoder->data.ptr; -} - -CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) -{ - return (size_t)(encoder->data.ptr - buffer); -} - -CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) -{ - return encoder->end ? 0 : (size_t)encoder->data.bytes_needed; -} - -/* Parser API */ - -enum CborParserIteratorFlags -{ - CborIteratorFlag_IntegerValueTooLarge = 0x01, - CborIteratorFlag_NegativeInteger = 0x02, - CborIteratorFlag_IteratingStringChunks = 0x02, - CborIteratorFlag_UnknownLength = 0x04, - CborIteratorFlag_ContainerIsMap = 0x20 -}; - -struct CborParser -{ - const uint8_t *end; - uint32_t flags; -}; -typedef struct CborParser CborParser; - -struct CborValue -{ - const CborParser *parser; - const uint8_t *ptr; - uint32_t remaining; - uint16_t extra; - uint8_t type; - uint8_t flags; -}; -typedef struct CborValue CborValue; - -CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it); - -CBOR_API CborError cbor_value_validate_basic(const CborValue *it); - -CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it) -{ return it->remaining == 0; } -CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it) -{ return it->ptr; } -CBOR_API CborError cbor_value_advance_fixed(CborValue *it); -CBOR_API CborError cbor_value_advance(CborValue *it); -CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it) -{ return it->type == CborArrayType || it->type == CborMapType; } -CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed); -CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed); - -CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value); -CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value) -{ - return value->flags & CborIteratorFlag_IntegerValueTooLarge ? - _cbor_value_decode_int64_internal(value) : value->extra; -} - -CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value) -{ return value && value->type != CborInvalidType; } -CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value) -{ return (CborType)value->type; } - -/* Null & undefined type */ -CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value) -{ return value->type == CborNullType; } -CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value) -{ return value->type == CborUndefinedType; } - -/* Booleans */ -CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value) -{ return value->type == CborBooleanType; } -CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result) -{ -#ifdef HOST - assert(cbor_value_is_boolean(value)); -#endif - *result = !!value->extra; - return CborNoError; -} - -/* Simple types */ -CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value) -{ return value->type == CborSimpleType; } -CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) -{ -#ifdef HOST - assert(cbor_value_is_simple_type(value)); -#endif - *result = (uint8_t)value->extra; - return CborNoError; -} - -/* Integers */ -CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value) -{ return value->type == CborIntegerType; } -CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; } -CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value) -{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); } - -CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_unsigned_integer(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = (int64_t) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result) -{ -#ifdef HOST - assert(cbor_value_is_integer(value)); -#endif - *result = (int) _cbor_value_extract_int64_helper(value); - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result); -CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result); - -CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value) -{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; } - -/* Tags */ -CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value) -{ return value->type == CborTagType; } -CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result) -{ -#ifdef HOST - assert(cbor_value_is_tag(value)); -#endif - *result = _cbor_value_extract_int64_helper(value); - return CborNoError; -} -CBOR_API CborError cbor_value_skip_tag(CborValue *it); - -/* Strings */ -CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value) -{ return value->type == CborByteStringType; } -CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value) -{ return value->type == CborTextStringType; } - -CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next); -CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer, - size_t *buflen, CborValue *next); - -CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length); - -CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_text_string(value)); -#endif - return _cbor_value_copy_string(value, buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_byte_string(value)); -#endif - return _cbor_value_copy_string(value, buffer, buflen, next); -} - -CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_text_string(value)); -#endif - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} -CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, - size_t *buflen, CborValue *next) -{ -#ifdef HOST - assert(cbor_value_is_byte_string(value)); -#endif - return _cbor_value_dup_string(value, (void **)buffer, buflen, next); -} - -CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result); - -/* Maps and arrays */ -CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value) -{ return value->type == CborArrayType; } -CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value) -{ return value->type == CborMapType; } - -CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_array(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length) -{ - uint64_t v; -#ifdef HOST - assert(cbor_value_is_map(value)); -#endif - if (!cbor_value_is_length_known(value)) - return CborErrorUnknownLength; - v = _cbor_value_extract_int64_helper(value); - *length = (size_t)v; - if (*length != v) - return CborErrorDataTooLarge; - return CborNoError; -} - -CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element); - -/* Floating point */ -CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value) -{ return value->type == CborHalfFloatType; } -CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result); - -CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value) -{ return value->type == CborFloatType; } -CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result) -{ - uint32_t data; -#ifdef HOST - assert(cbor_value_is_float(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); -#endif - data = (uint32_t)_cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value) -{ return value->type == CborDoubleType; } -CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result) -{ - uint64_t data; -#ifdef HOST - assert(cbor_value_is_double(value)); - assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); -#endif - data = _cbor_value_decode_int64_internal(value); - memcpy(result, &data, sizeof(*result)); - return CborNoError; -} - -/* Validation API */ - -enum CborValidationFlags { - /* Bit mapping: - * bits 0-7 (8 bits): canonical format - * bits 8-11 (4 bits): canonical format & strict mode - * bits 12-20 (8 bits): strict mode - * bits 21-31 (10 bits): other - */ - - CborValidateShortestIntegrals = 0x0001, - CborValidateShortestFloatingPoint = 0x0002, - CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint, - CborValidateNoIndeterminateLength = 0x0100, - CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength, - - CborValidateCanonicalFormat = 0x0fff, - - CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted, - CborValidateTagUse = 0x2000, - CborValidateUtf8 = 0x4000, - - CborValidateStrictMode = 0xfff00, - - CborValidateMapKeysAreString = 0x100000, - CborValidateNoUndefined = 0x200000, - CborValidateNoTags = 0x400000, - CborValidateFiniteFloatingPoint = 0x800000, - /* unused = 0x1000000, */ - /* unused = 0x2000000, */ - - CborValidateNoUnknownSimpleTypesSA = 0x4000000, - CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA, - CborValidateNoUnknownTagsSA = 0x10000000, - CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA, - CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR, - - CborValidateCompleteData = (int)0x80000000, - - CborValidateStrictest = (int)~0U, - CborValidateBasic = 0 -}; - -CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags); - -/* Human-readable (dump) API */ - -enum CborPrettyFlags { - CborPrettyNumericEncodingIndicators = 0x01, - CborPrettyTextualEncodingIndicators = 0, - - CborPrettyIndicateIndeterminateLength = 0x02, - CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */ - CborPrettyIndicateOverlongNumbers = 0x04, - - CborPrettyShowStringFragments = 0x100, - CborPrettyMergeStringFragments = 0, - - CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength -}; - -typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...) -#ifdef __GNUC__ - __attribute__((__format__(printf, 2, 3))) -#endif -; - -CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags); - -/* The following API requires a hosted C implementation (uses FILE*) */ -#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1 -CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags); -CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value); -CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value) -{ - CborValue copy = *value; - return cbor_value_to_pretty_advance_flags(out, ©, CborPrettyDefaultFlags); -} -#endif /* __STDC_HOSTED__ check */ - -#ifdef __cplusplus -} -#endif - -#endif /* CBOR_H */ - diff --git a/src/cbor/lib/tinycbor/src/cborencoder.c b/src/cbor/lib/tinycbor/src/cborencoder.c deleted file mode 100644 index 23a9721ad..000000000 --- a/src/cbor/lib/tinycbor/src/cborencoder.c +++ /dev/null @@ -1,650 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborEncoding Encoding to CBOR - * \brief Group of functions used to encode data to CBOR. - * - * CborEncoder is used to encode data into a CBOR stream. The outermost - * CborEncoder is initialized by calling cbor_encoder_init(), with the buffer - * where the CBOR stream will be stored. The outermost CborEncoder is usually - * used to encode exactly one item, most often an array or map. It is possible - * to encode more than one item, but care must then be taken on the decoder - * side to ensure the state is reset after each item was decoded. - * - * Nested CborEncoder objects are created using cbor_encoder_create_array() and - * cbor_encoder_create_map(), later closed with cbor_encoder_close_container() - * or cbor_encoder_close_container_checked(). The pairs of creation and closing - * must be exactly matched and their parameters are always the same. - * - * CborEncoder writes directly to the user-supplied buffer, without extra - * buffering. CborEncoder does not allocate memory and CborEncoder objects are - * usually created on the stack of the encoding functions. - * - * The example below initializes a CborEncoder object with a buffer and encodes - * a single integer. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * cbor_encode_int(&encoder, some_value); - * \endcode - * - * As explained before, usually the outermost CborEncoder object is used to add - * one array or map, which in turn contains multiple elements. The example - * below creates a CBOR map with one element: a key "foo" and a boolean value. - * - * \code - * uint8_t buf[16]; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * cbor_encode_text_stringz(&mapEncoder, "foo"); - * cbor_encode_boolean(&mapEncoder, some_value); - * cbor_encoder_close_container(&encoder, &mapEncoder); - * \endcode - * - *

Error checking and buffer size

- * - * All functions operating on CborEncoder return a condition of type CborError. - * If the encoding was successful, they return CborNoError. Some functions do - * extra checking on the input provided and may return some other error - * conditions (for example, cbor_encode_simple_value() checks that the type is - * of the correct type). - * - * In addition, all functions check whether the buffer has enough bytes to - * encode the item being appended. If that is not possible, they return - * CborErrorOutOfMemory. - * - * It is possible to continue with the encoding of data past the first function - * that returns CborErrorOutOfMemory. CborEncoder functions will not overrun - * the buffer, but will instead count how many more bytes are needed to - * complete the encoding. At the end, you can obtain that count by calling - * cbor_encoder_get_extra_bytes_needed(). - * - * \section1 Finalizing the encoding - * - * Once all items have been appended and the containers have all been properly - * closed, the user-supplied buffer will contain the CBOR stream and may be - * immediately used. To obtain the size of the buffer, call - * cbor_encoder_get_buffer_size() with the original buffer pointer. - * - * The example below illustrates how one can encode an item with error checking - * and then pass on the buffer for network sending. - * - * \code - * uint8_t buf[16]; - * CborError err; - * CborEncoder encoder, mapEncoder; - * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); - * err = cbor_encoder_create_map(&encoder, &mapEncoder, 1); - * if (!err) - * return err; - * err = cbor_encode_text_stringz(&mapEncoder, "foo"); - * if (!err) - * return err; - * err = cbor_encode_boolean(&mapEncoder, some_value); - * if (!err) - * return err; - * err = cbor_encoder_close_container_checked(&encoder, &mapEncoder); - * if (!err) - * return err; - * - * size_t len = cbor_encoder_get_buffer_size(&encoder, buf); - * send_payload(buf, len); - * return CborNoError; - * \endcode - * - * Finally, the example below expands on the one above and also - * deals with dynamically growing the buffer if the initial allocation wasn't - * big enough. Note the two places where the error checking was replaced with - * an cbor_assertion, showing where the author assumes no error can occur. - * - * \code - * uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize) - * { - * CborError err; - * CborEncoder encoder, arrayEncoder; - * size_t size = 256; - * uint8_t *buf = NULL; - * - * while (1) { - * int i; - * size_t more_bytes; - * uint8_t *nbuf = realloc(buf, size); - * if (nbuf == NULL) - * goto error; - * buf = nbuf; - * - * cbor_encoder_init(&encoder, &buf, size, 0); - * err = cbor_encoder_create_array(&encoder, &arrayEncoder, n); - * cbor_assert(err); // can't fail, the buffer is always big enough - * - * for (i = 0; i < n; ++i) { - * err = cbor_encode_text_stringz(&arrayEncoder, strings[i]); - * if (err && err != CborErrorOutOfMemory) - * goto error; - * } - * - * err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder); - * cbor_assert(err); // shouldn't fail! - * - * more_bytes = cbor_encoder_get_extra_bytes_needed(encoder); - * if (more_size) { - * // buffer wasn't big enough, try again - * size += more_bytes; - * continue; - * } - * - * *bufsize = cbor_encoder_get_buffer_size(encoder, buf); - * return buf; - * } - * error: - * free(buf); - * return NULL; - * } - * \endcode - */ - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * \struct CborEncoder - * Structure used to encode to CBOR. - */ - -/** - * Initializes a CborEncoder structure \a encoder by pointing it to buffer \a - * buffer of size \a size. The \a flags field is currently unused and must be - * zero. - */ -void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags) -{ - encoder->data.ptr = buffer; - encoder->end = buffer + size; - encoder->remaining = 2; - encoder->flags = flags; -} - -static inline void put16(void *where, uint16_t v) -{ - v = cbor_htons(v); - memcpy(where, &v, sizeof(v)); -} - -/* Note: Since this is currently only used in situations where OOM is the only - * valid error, we KNOW this to be true. Thus, this function now returns just 'true', - * but if in the future, any function starts returning a non-OOM error, this will need - * to be changed to the test. At the moment, this is done to prevent more branches - * being created in the tinycbor output */ -static inline bool isOomError(CborError err) -{ - (void) err; - return true; -} - -static inline void put32(void *where, uint32_t v) -{ - v = cbor_htonl(v); - memcpy(where, &v, sizeof(v)); -} - -static inline void put64(void *where, uint64_t v) -{ - v = cbor_htonll(v); - memcpy(where, &v, sizeof(v)); -} - -static inline bool would_overflow(CborEncoder *encoder, size_t len) -{ - ptrdiff_t remaining = (ptrdiff_t)encoder->end; - remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; - remaining -= (ptrdiff_t)len; - return unlikely(remaining < 0); -} - -static inline void advance_ptr(CborEncoder *encoder, size_t n) -{ - if (encoder->end) - encoder->data.ptr += n; - else - encoder->data.bytes_needed += n; -} - -static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) -{ - if (would_overflow(encoder, len)) { - if (encoder->end != NULL) { - len -= encoder->end - encoder->data.ptr; - encoder->end = NULL; - encoder->data.bytes_needed = 0; - } - - advance_ptr(encoder, len); - return CborErrorOutOfMemory; - } - - memcpy(encoder->data.ptr, data, len); - encoder->data.ptr += len; - return CborNoError; -} - -static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) -{ - return append_to_buffer(encoder, &byte, 1); -} - -static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - /* Little-endian would have been so much more convenient here: - * We could just write at the beginning of buf but append_to_buffer - * only the necessary bytes. - * Since it has to be big endian, do it the other way around: - * write from the end. */ - uint64_t buf[2]; - uint8_t *const bufend = (uint8_t *)buf + sizeof(buf); - uint8_t *bufstart = bufend - 1; - put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */ - - if (ui < Value8Bit) { - *bufstart += shiftedMajorType; - } else { - uint8_t more = 0; - if (ui > 0xffU) - ++more; - if (ui > 0xffffU) - ++more; - if (ui > 0xffffffffU) - ++more; - bufstart -= (size_t)1 << more; - *bufstart = shiftedMajorType + Value8Bit + more; - } - - return append_to_buffer(encoder, bufstart, bufend - bufstart); -} - -static inline void saturated_decrement(CborEncoder *encoder) -{ - if (encoder->remaining) - --encoder->remaining; -} - -static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) -{ - saturated_decrement(encoder); - return encode_number_no_update(encoder, ui, shiftedMajorType); -} - -/** - * Appends the unsigned 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_int - */ -CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value) -{ - return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift); -} - -/** - * Appends the negative 64-bit integer whose absolute value is \a - * absolute_value to the CBOR stream provided by \a encoder. - * - * If the value \a absolute_value is zero, this function encodes -2^64. - * - * \sa cbor_encode_uint, cbor_encode_int - */ -CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value) -{ - return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift); -} - -/** - * Appends the signed 64-bit integer \a value to the CBOR stream provided by - * \a encoder. - * - * \sa cbor_encode_negative_int, cbor_encode_uint - */ -CborError cbor_encode_int(CborEncoder *encoder, int64_t value) -{ - /* adapted from code in RFC 7049 appendix C (pseudocode) */ - uint64_t ui = value >> 63; /* extend sign to whole length */ - uint8_t majorType = ui & 0x20; /* extract major type */ - ui ^= value; /* complement negatives */ - return encode_number(encoder, ui, majorType); -} - -/** - * Appends the CBOR Simple Type of value \a value to the CBOR stream provided by - * \a encoder. - * - * This function may return error CborErrorIllegalSimpleType if the \a value - * variable contains a number that is not a valid simple type. - */ -CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value) -{ -#ifndef CBOR_ENCODER_NO_CHECK_USER - /* check if this is a valid simple type */ - if (value >= HalfPrecisionFloat && value <= Break) - return CborErrorIllegalSimpleType; -#endif - return encode_number(encoder, value, SimpleTypesType << MajorTypeShift); -} - -/** - * Appends the floating-point value of type \a fpType and pointed to by \a - * value to the CBOR stream provided by \a encoder. The value of \a fpType must - * be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the - * behavior of this function is undefined. - * - * This function is useful for code that needs to pass through floating point - * values but does not wish to have the actual floating-point code. - * - * \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double - */ -CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value) -{ - unsigned size; - uint8_t buf[1 + sizeof(uint64_t)]; - cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType); - buf[0] = fpType; - - size = 2U << (fpType - CborHalfFloatType); - if (size == 8) - put64(buf + 1, *(const uint64_t*)value); - else if (size == 4) - put32(buf + 1, *(const uint32_t*)value); - else - put16(buf + 1, *(const uint16_t*)value); - saturated_decrement(encoder); - return append_to_buffer(encoder, buf, size + 1); -} - -/** - * Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder. - * - * \sa CborTag - */ -CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag) -{ - /* tags don't count towards the number of elements in an array or map */ - return encode_number_no_update(encoder, tag, TagType << MajorTypeShift); -} - -static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string) -{ - CborError err = encode_number(encoder, length, shiftedMajorType); - if (err && !isOomError(err)) - return err; - return append_to_buffer(encoder, string, length); -} - -/** - * \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) - * - * Appends the null-terminated text string \a string to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. The terminating null is not - * included in the stream. - * - * \sa cbor_encode_text_string, cbor_encode_byte_string - */ - -/** - * Appends the text string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but - * TinyCBOR makes no verification of correctness. - * - * \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string - */ -CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length) -{ - return encode_string(encoder, length, ByteStringType << MajorTypeShift, string); -} - -/** - * Appends the byte string \a string of length \a length to the CBOR stream - * provided by \a encoder. CBOR byte strings are arbitrary raw data. - * - * \sa cbor_encode_text_stringz, cbor_encode_text_string - */ -CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length) -{ - return encode_string(encoder, length, TextStringType << MajorTypeShift, string); -} - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType) -{ - CborError err; - container->data.ptr = encoder->data.ptr; - container->end = encoder->end; - saturated_decrement(encoder); - container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */ - - cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap); - cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0); - container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap; - - if (length == CborIndefiniteLength) { - container->flags |= CborIteratorFlag_UnknownLength; - err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength); - } else { - if (shiftedMajorType & CborIteratorFlag_ContainerIsMap) - container->remaining += length; - err = encode_number_no_update(container, length, shiftedMajorType); - } - return err; -} - -/** - * Creates a CBOR array in the CBOR stream provided by \a encoder and - * initializes \a arrayEncoder so that items can be added to the array using - * the CborEncoder functions. The array must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a arrayEncoder parameters. - * - * The number of items inserted into the array must be exactly \a length items, - * otherwise the stream is invalid. If the number of items is not known when - * creating the array, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \sa cbor_encoder_create_map - */ -CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length) -{ - return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift); -} - -/** - * Creates a CBOR map in the CBOR stream provided by \a encoder and - * initializes \a mapEncoder so that items can be added to the map using - * the CborEncoder functions. The map must be terminated by calling either - * cbor_encoder_close_container() or cbor_encoder_close_container_checked() - * with the same \a encoder and \a mapEncoder parameters. - * - * The number of pair of items inserted into the map must be exactly \a length - * items, otherwise the stream is invalid. If the number is not known - * when creating the map, the constant \ref CborIndefiniteLength may be passed as - * length instead. - * - * \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2 - * key-value pairs in the stream. If the length \a length is larger than this - * value (and is not \ref CborIndefiniteLength), this function returns error - * CborErrorDataTooLarge. - * - * \sa cbor_encoder_create_array - */ -CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length) -{ - if (length != CborIndefiniteLength && length > SIZE_MAX / 2) - return CborErrorDataTooLarge; - return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift); -} - -/** - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Since version 0.5, this function verifies that the number of items (or pairs - * of items, in the case of a map) was correct. It is no longer necessary to call - * cbor_encoder_close_container_checked() instead. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - if (encoder->end) - encoder->data.ptr = containerEncoder->data.ptr; - else - encoder->data.bytes_needed = containerEncoder->data.bytes_needed; - encoder->end = containerEncoder->end; - if (containerEncoder->flags & CborIteratorFlag_UnknownLength) - return append_byte_to_buffer(encoder, BreakByte); - - if (containerEncoder->remaining != 1) - return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems; - - if (!encoder->end) - return CborErrorOutOfMemory; /* keep the state */ - return CborNoError; -} - -/** - * \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value) - * - * Appends the boolean value \a value to the CBOR stream provided by \a encoder. - */ - -/** - * \fn CborError cbor_encode_null(CborEncoder *encoder) - * - * Appends the CBOR type representing a null value to the CBOR stream provided - * by \a encoder. - * - * \sa cbor_encode_undefined() - */ - -/** - * \fn CborError cbor_encode_undefined(CborEncoder *encoder) - * - * Appends the CBOR type representing an undefined value to the CBOR stream - * provided by \a encoder. - * - * \sa cbor_encode_null() - */ - -/** - * \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) - * - * Appends the IEEE 754 half-precision (16-bit) floating point value pointed to - * by \a value to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_float(CborEncoder *encoder, float value) - * - * Appends the IEEE 754 single-precision (32-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double() - */ - -/** - * \fn CborError cbor_encode_double(CborEncoder *encoder, double value) - * - * Appends the IEEE 754 double-precision (64-bit) floating point value \a value - * to the CBOR stream provided by \a encoder. - * - * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float() - */ - -/** - * \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) - * - * Returns the total size of the buffer starting at \a buffer after the - * encoding finished without errors. The \a encoder and \a buffer arguments - * must be the same as supplied to cbor_encoder_init(). - * - * If the encoding process had errors, the return value of this function is - * meaningless. If the only errors were CborErrorOutOfMemory, instead use - * cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the - * buffer before encoding again. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding - */ - -/** - * \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) - * - * Returns how many more bytes the original buffer supplied to - * cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory - * condition will happen for the encoding. If the buffer was big enough, this - * function returns 0. The \a encoder must be the original argument as passed - * to cbor_encoder_init(). - * - * This function is usually called after an encoding sequence ended with one or - * more CborErrorOutOfMemory errors, but no other error. If any other error - * happened, the return value of this function is meaningless. - * - * See \ref CborEncoding for an example of using this function. - * - * \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding - */ - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c b/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c deleted file mode 100644 index 1165d370f..000000000 --- a/src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \addtogroup CborEncoding - * @{ - */ - -/** - * @deprecated - * - * Closes the CBOR container (array or map) provided by \a containerEncoder and - * updates the CBOR stream provided by \a encoder. Both parameters must be the - * same as were passed to cbor_encoder_create_array() or - * cbor_encoder_create_map(). - * - * Prior to version 0.5, cbor_encoder_close_container() did not check the - * number of items added. Since that version, it does and now - * cbor_encoder_close_container_checked() is no longer needed. - * - * \sa cbor_encoder_create_array(), cbor_encoder_create_map() - */ -CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder) -{ - return cbor_encoder_close_container(encoder, containerEncoder); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborerrorstrings.c b/src/cbor/lib/tinycbor/src/cborerrorstrings.c deleted file mode 100644 index d0ba66c34..000000000 --- a/src/cbor/lib/tinycbor/src/cborerrorstrings.c +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "cbor.h" - -#ifndef _ -# define _(msg) msg -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \enum CborError - * \ingroup CborGlobals - * The CborError enum contains the possible error values used by the CBOR encoder and decoder. - * - * TinyCBOR functions report success by returning CborNoError, or one error - * condition by returning one of the values below. One exception is the - * out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref - * CborEncoding may report in bit-wise OR with other conditions. - * - * This technique allows code to determine whether the only error condition was - * a lack of buffer space, which may not be a fatal condition if the buffer can - * be resized. Additionally, the functions for \ref CborEncoding may continue - * to be used even after CborErrorOutOfMemory is returned, and instead they - * will simply calculate the extra space needed. - * - * \value CborNoError No error occurred - * \omitvalue CborUnknownError - * \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream - * \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream) - * \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation - * \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream - * \value CborErrorUnexpectedEOF End of stream reached unexpectedly - * \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected - * \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream - * \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string - * \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found - * \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found - * \omitvalue CborErrorUnknownSimpleType - * \omitvalue CborErrorUnknownTag - * \omitvalue CborErrorInappropriateTagForType - * \omitvalue CborErrorDuplicateObjectKeys - * \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String - * \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length - * \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length - * \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits - * \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits - * \omitvalue CborErrorUnsupportedType - * \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array - * \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string - * \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item; - * in other situations, TinyCBOR failed to allocate memory - * \value CborErrorInternalError An internal error occurred in TinyCBOR - */ - -/** - * \ingroup CborGlobals - * Returns the error string corresponding to the CBOR error condition \a error. - */ -const char *cbor_error_string(CborError error) -{ - switch (error) { - case CborNoError: - return ""; - - case CborUnknownError: - return _("unknown error"); - - case CborErrorOutOfMemory: - return _("out of memory/need more memory"); - - case CborErrorUnknownLength: - return _("unknown length (attempted to get the length of a map/array/string of indeterminate length"); - - case CborErrorAdvancePastEOF: - return _("attempted to advance past EOF"); - - case CborErrorIO: - return _("I/O error"); - - case CborErrorGarbageAtEnd: - return _("garbage after the end of the content"); - - case CborErrorUnexpectedEOF: - return _("unexpected end of data"); - - case CborErrorUnexpectedBreak: - return _("unexpected 'break' byte"); - - case CborErrorUnknownType: - return _("illegal byte (encodes future extension type)"); - - case CborErrorIllegalType: - return _("mismatched string type in chunked string"); - - case CborErrorIllegalNumber: - return _("illegal initial byte (encodes unspecified additional information)"); - - case CborErrorIllegalSimpleType: - return _("illegal encoding of simple type smaller than 32"); - - case CborErrorUnknownSimpleType: - return _("unknown simple type"); - - case CborErrorUnknownTag: - return _("unknown tag"); - - case CborErrorInappropriateTagForType: - return _("inappropriate tag for type"); - - case CborErrorDuplicateObjectKeys: - return _("duplicate keys in object"); - - case CborErrorInvalidUtf8TextString: - return _("invalid UTF-8 content in string"); - - case CborErrorExcludedType: - return _("excluded type found"); - - case CborErrorExcludedValue: - return _("excluded value found"); - - case CborErrorImproperValue: - case CborErrorOverlongEncoding: - return _("value encoded in non-canonical form"); - - case CborErrorMapKeyNotString: - case CborErrorJsonObjectKeyNotString: - return _("key in map is not a string"); - - case CborErrorMapNotSorted: - return _("map is not sorted"); - - case CborErrorMapKeysNotUnique: - return _("map keys are not unique"); - - case CborErrorTooManyItems: - return _("too many items added to encoder"); - - case CborErrorTooFewItems: - return _("too few items added to encoder"); - - case CborErrorSplitItems: - return _("splitted item added to encoder"); - - case CborErrorDataTooLarge: - return _("internal error: data too large"); - - case CborErrorNestingTooDeep: - return _("internal error: too many nested containers found in recursive function"); - - case CborErrorUnsupportedType: - return _("unsupported type"); - - case CborErrorJsonObjectKeyIsAggregate: - return _("conversion to JSON failed: key in object is an array or map"); - - case CborErrorJsonNotImplemented: - return _("conversion to JSON failed: open_memstream unavailable"); - - case CborErrorInternalError: - return _("internal error"); - } - return cbor_error_string(CborUnknownError); -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cborinternal_p.h b/src/cbor/lib/tinycbor/src/cborinternal_p.h deleted file mode 100644 index a85a92972..000000000 --- a/src/cbor/lib/tinycbor/src/cborinternal_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBORINTERNAL_P_H -#define CBORINTERNAL_P_H - -#include "compilersupport_p.h" - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#else -# ifndef CBOR_NO_HALF_FLOAT_TYPE -# define CBOR_NO_HALF_FLOAT_TYPE 1 -# endif -#endif - -#ifndef CBOR_NO_HALF_FLOAT_TYPE -# ifdef __F16C__ -# include -static inline unsigned short encode_half(double val) -{ - return _cvtss_sh((float)val, 3); -} -static inline double decode_half(unsigned short half) -{ - return _cvtsh_ss(half); -} -# else -/* software implementation of float-to-fp16 conversions */ -static inline unsigned short encode_half(double val) -{ - uint64_t v; - int sign, exp, mant; - memcpy(&v, &val, sizeof(v)); - sign = v >> 63 << 15; - exp = (v >> 52) & 0x7ff; - mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */ - exp -= 1023; - if (exp == 1024) { - /* infinity or NaN */ - exp = 16; - mant >>= 1; - } else if (exp >= 16) { - /* overflow, as largest number */ - exp = 15; - mant = 1023; - } else if (exp >= -14) { - /* regular normal */ - } else if (exp >= -24) { - /* subnormal */ - mant |= 1024; - mant >>= -(exp + 14); - exp = -15; - } else { - /* underflow, make zero */ - return 0; - } - - /* safe cast here as bit operations above guarantee not to overflow */ - return (unsigned short)(sign | ((exp + 15) << 10) | mant); -} - -/* this function was copied & adapted from RFC 7049 Appendix D */ -static inline double decode_half(unsigned short half) -{ - int exp = (half >> 10) & 0x1f; - int mant = half & 0x3ff; - double val; - if (exp == 0) val = ldexp(mant, -24); - else if (exp != 31) val = ldexp(mant + 1024, exp - 25); - else val = mant == 0 ? INFINITY : NAN; - return half & 0x8000 ? -val : val; -} -# endif -#endif /* CBOR_NO_HALF_FLOAT_TYPE */ - -#ifndef CBOR_INTERNAL_API -# define CBOR_INTERNAL_API -#endif - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -/* - * CBOR Major types - * Encoded in the high 3 bits of the descriptor byte - * See http://tools.ietf.org/html/rfc7049#section-2.1 - */ -typedef enum CborMajorTypes { - UnsignedIntegerType = 0U, - NegativeIntegerType = 1U, - ByteStringType = 2U, - TextStringType = 3U, - ArrayType = 4U, - MapType = 5U, /* a.k.a. object */ - TagType = 6U, - SimpleTypesType = 7U -} CborMajorTypes; - -/* - * CBOR simple and floating point types - * Encoded in the low 8 bits of the descriptor byte when the - * Major Type is 7. - */ -typedef enum CborSimpleTypes { - FalseValue = 20, - TrueValue = 21, - NullValue = 22, - UndefinedValue = 23, - SimpleTypeInNextByte = 24, /* not really a simple type */ - HalfPrecisionFloat = 25, /* ditto */ - SinglePrecisionFloat = 26, /* ditto */ - DoublePrecisionFloat = 27, /* ditto */ - Break = 31 -} CborSimpleTypes; - -enum { - SmallValueBitLength = 5U, - SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */ - Value8Bit = 24U, - Value16Bit = 25U, - Value32Bit = 26U, - Value64Bit = 27U, - IndefiniteLength = 31U, - - MajorTypeShift = SmallValueBitLength, - MajorTypeMask = (int) (~0U << MajorTypeShift), - - BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift) -}; - -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it); -CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next); - - -#endif /* CBORINTERNAL_P_H */ diff --git a/src/cbor/lib/tinycbor/src/cborjson.h b/src/cbor/lib/tinycbor/src/cborjson.h deleted file mode 100644 index 8ff27b920..000000000 --- a/src/cbor/lib/tinycbor/src/cborjson.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBORJSON_H -#define CBORJSON_H - -#include "cbor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Conversion to JSON */ -enum CborToJsonFlags -{ - CborConvertAddMetadata = 1, - CborConvertTagsToObjects = 2, - CborConvertIgnoreTags = 0, - - CborConvertObeyByteStringTags = 0, - CborConvertByteStringsToBase64Url = 4, - - CborConvertRequireMapStringKeys = 0, - CborConvertStringifyMapKeys = 8, - - CborConvertDefaultFlags = 0 -}; - -CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags); -CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) -{ - CborValue copy = *value; - return cbor_value_to_json_advance(out, ©, flags); -} - -#ifdef __cplusplus -} -#endif - -#endif /* CBORJSON_H */ - diff --git a/src/cbor/lib/tinycbor/src/cborparser.c b/src/cbor/lib/tinycbor/src/cborparser.c deleted file mode 100644 index 428159231..000000000 --- a/src/cbor/lib/tinycbor/src/cborparser.c +++ /dev/null @@ -1,1435 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborParsing Parsing CBOR streams - * \brief Group of functions used to parse CBOR streams. - * - * TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded - * payload. The main data type for the parsing is a CborValue, which behaves - * like an iterator and can be used to extract the encoded data. It is first - * initialized with a call to cbor_parser_init() and is usually used to extract - * exactly one item, most often an array or map. - * - * Nested CborValue objects can be parsed using cbor_value_enter_container(). - * Each call to cbor_value_enter_container() must be matched by a call to - * cbor_value_leave_container(), with the exact same parameters. - * - * The example below initializes a CborParser object, begins the parsing with a - * CborValue and decodes a single integer: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * cbor_parser_init(buffer, len, 0, &parser, &value); - * cbor_value_get_int(&value, &result); - * return result; - * } - * \endcode - * - * The code above does no error checking, which means it assumes the data comes - * from a source trusted to send one properly-encoded integer. The following - * example does the exact same operation, but includes error checking and - * returns 0 on parsing failure: - * - * \code - * int extract_int(const uint8_t *buffer, size_t len) - * { - * CborParser parser; - * CborValue value; - * int result; - * if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError) - * return 0; - * if (!cbor_value_is_integer(&value) || - * cbor_value_get_int(&value, &result) != CborNoError) - * return 0; - * return result; - * } - * \endcode - * - * Note, in the example above, that one can't distinguish a parsing failure - * from an encoded value of zero. Reporting a parsing error is left as an - * exercise to the reader. - * - * The code above does not execute a range-check either: it is possible that - * the value decoded from the CBOR stream encodes a number larger than what can - * be represented in a variable of type \c{int}. If detecting that case is - * important, the code should call cbor_value_get_int_checked() instead. - * - *

Memory and parsing constraints

- * - * TinyCBOR is designed to run with little memory and with minimal overhead. - * Except where otherwise noted, the parser functions always run on constant - * time (O(1)), do not recurse and never allocate memory (thus, stack usage is - * bounded and is O(1)). - * - *

Error handling and preconditions

- * - * All functions operating on a CborValue return a CborError condition, with - * CborNoError standing for the normal situation in which no parsing error - * occurred. All functions may return parsing errors in case the stream cannot - * be decoded properly, be it due to corrupted data or due to reaching the end - * of the input buffer. - * - * Error conditions must not be ignored. All decoder functions have undefined - * behavior if called after an error has been reported, and may crash. - * - * Some functions are also documented to have preconditions, like - * cbor_value_get_int() requiring that the input be an integral value. - * Violation of preconditions also results in undefined behavior and the - * program may crash. - */ - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \struct CborValue - * - * This type contains one value parsed from the CBOR stream. Each CborValue - * behaves as an iterator in a StAX-style parser. - * - * \if privatedocs - * Implementation details: the CborValue contains these fields: - * \list - * \li ptr: pointer to the actual data - * \li flags: flags from the decoder - * \li extra: partially decoded integer value (0, 1 or 2 bytes) - * \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown - * \endlist - * \endif - */ - -static inline uint16_t get16(const uint8_t *ptr) -{ - uint16_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohs(result); -} - -static inline uint32_t get32(const uint8_t *ptr) -{ - uint32_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohl(result); -} - -static inline uint64_t get64(const uint8_t *ptr) -{ - uint64_t result; - memcpy(&result, ptr, sizeof(result)); - return cbor_ntohll(result); -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len) -{ - size_t bytesNeeded; - uint8_t additional_information = **ptr & SmallValueMask; - ++*ptr; - if (additional_information < Value8Bit) { - *len = additional_information; - return CborNoError; - } - if (unlikely(additional_information > Value64Bit)) - return CborErrorIllegalNumber; - - bytesNeeded = (size_t)(1 << (additional_information - Value8Bit)); - if (unlikely(bytesNeeded > (size_t)(end - *ptr))) { - return CborErrorUnexpectedEOF; - } else if (bytesNeeded == 1) { - *len = (uint8_t)(*ptr)[0]; - } else if (bytesNeeded == 2) { - *len = get16(*ptr); - } else if (bytesNeeded == 4) { - *len = get32(*ptr); - } else { - *len = get64(*ptr); - } - *ptr += bytesNeeded; - return CborNoError; -} - -static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len) -{ - uint64_t v; - CborError err = _cbor_value_extract_number(ptr, parser->end, &v); - if (err) { - *len = 0; - return err; - } - - *len = (size_t)v; - if (v != *len) - return CborErrorDataTooLarge; - return CborNoError; -} - -static bool is_fixed_type(uint8_t type) -{ - return type != CborTextStringType && type != CborByteStringType && type != CborArrayType && - type != CborMapType; -} - -static CborError preparse_value(CborValue *it) -{ - const CborParser *parser = it->parser; - it->type = CborInvalidType; - - /* are we at the end? */ - if (it->ptr == parser->end) - return CborErrorUnexpectedEOF; - - uint8_t descriptor = *it->ptr; - uint8_t type = descriptor & MajorTypeMask; - it->type = type; - it->flags = 0; - it->extra = (descriptor &= SmallValueMask); - - if (descriptor > Value64Bit) { - if (unlikely(descriptor != IndefiniteLength)) - return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber; - if (likely(!is_fixed_type(type))) { - /* special case */ - it->flags |= CborIteratorFlag_UnknownLength; - it->type = type; - return CborNoError; - } - return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber; - } - - size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit)); - if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - uint8_t majortype = type >> MajorTypeShift; - if (majortype == NegativeIntegerType) { - it->flags |= CborIteratorFlag_NegativeInteger; - it->type = CborIntegerType; - } else if (majortype == SimpleTypesType) { - switch (descriptor) { - case FalseValue: - it->extra = false; - it->type = CborBooleanType; - break; - - case SinglePrecisionFloat: - case DoublePrecisionFloat: - it->flags |= CborIteratorFlag_IntegerValueTooLarge; - /* fall through */ - case TrueValue: - case NullValue: - case UndefinedValue: - case HalfPrecisionFloat: - it->type = *it->ptr; - break; - - case SimpleTypeInNextByte: - it->extra = (uint8_t)it->ptr[1]; -#ifndef CBOR_PARSER_NO_STRICT_CHECKS - if (unlikely(it->extra < 32)) { - it->type = CborInvalidType; - return CborErrorIllegalSimpleType; - } -#endif - break; - - case 28: - case 29: - case 30: - case Break: - cbor_assert(false); /* these conditions can't be reached */ - return CborErrorUnexpectedBreak; - } - return CborNoError; - } - - /* try to decode up to 16 bits */ - if (descriptor < Value8Bit) - return CborNoError; - - if (descriptor == Value8Bit) - it->extra = (uint8_t)it->ptr[1]; - else if (descriptor == Value16Bit) - it->extra = get16(it->ptr + 1); - else - it->flags |= CborIteratorFlag_IntegerValueTooLarge; /* Value32Bit or Value64Bit */ - return CborNoError; -} - -static CborError preparse_next_value_nodecrement(CborValue *it) -{ - if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) { - /* end of map or array */ - ++it->ptr; - it->type = CborInvalidType; - it->remaining = 0; - return CborNoError; - } - - return preparse_value(it); -} - -static CborError preparse_next_value(CborValue *it) -{ - if (it->remaining != UINT32_MAX) { - /* don't decrement the item count if the current item is tag: they don't count */ - if (it->type != CborTagType && --it->remaining == 0) { - it->type = CborInvalidType; - return CborNoError; - } - } - return preparse_next_value_nodecrement(it); -} - -static CborError advance_internal(CborValue *it) -{ - uint64_t length; - CborError err = _cbor_value_extract_number(&it->ptr, it->parser->end, &length); - cbor_assert(err == CborNoError); - - if (it->type == CborByteStringType || it->type == CborTextStringType) { - cbor_assert(length == (size_t)length); - cbor_assert((it->flags & CborIteratorFlag_UnknownLength) == 0); - it->ptr += length; - } - - return preparse_next_value(it); -} - -/** \internal - * - * Decodes the CBOR integer value when it is larger than the 16 bits available - * in value->extra. This function requires that value->flags have the - * CborIteratorFlag_IntegerValueTooLarge flag set. - * - * This function is also used to extract single- and double-precision floating - * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat == - * Value64Bit). - */ -uint64_t _cbor_value_decode_int64_internal(const CborValue *value) -{ - cbor_assert(value->flags & CborIteratorFlag_IntegerValueTooLarge || - value->type == CborFloatType || value->type == CborDoubleType); - - /* since the additional information can only be Value32Bit or Value64Bit, - * we just need to test for the one bit those two options differ */ - cbor_assert((*value->ptr & SmallValueMask) == Value32Bit || (*value->ptr & SmallValueMask) == Value64Bit); - if ((*value->ptr & 1) == (Value32Bit & 1)) - return get32(value->ptr + 1); - - cbor_assert((*value->ptr & SmallValueMask) == Value64Bit); - return get64(value->ptr + 1); -} - -/** - * Initializes the CBOR parser for parsing \a size bytes beginning at \a - * buffer. Parsing will use flags set in \a flags. The iterator to the first - * element is returned in \a it. - * - * The \a parser structure needs to remain valid throughout the decoding - * process. It is not thread-safe to share one CborParser among multiple - * threads iterating at the same time, but the object can be copied so multiple - * threads can iterate. - */ -CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it) -{ - memset(parser, 0, sizeof(*parser)); - parser->end = buffer + size; - parser->flags = flags; - it->parser = parser; - it->ptr = buffer; - it->remaining = 1; /* there's one type altogether, usually an array or map */ - return preparse_value(it); -} - -/** - * \fn bool cbor_value_at_end(const CborValue *it) - * - * Returns true if \a it has reached the end of the iteration, usually when - * advancing after the last item in an array or map. - * - * In the case of the outermost CborValue object, this function returns true - * after decoding a single element. A pointer to the first byte of the - * remaining data (if any) can be obtained with cbor_value_get_next_byte(). - * - * \sa cbor_value_advance(), cbor_value_is_valid(), cbor_value_get_next_byte() - */ - -/** - * \fn const uint8_t *cbor_value_get_next_byte(const CborValue *it) - * - * Returns a pointer to the next byte that would be decoded if this CborValue - * object were advanced. - * - * This function is useful if cbor_value_at_end() returns true for the - * outermost CborValue: the pointer returned is the first byte of the data - * remaining in the buffer, if any. Code can decide whether to begin decoding a - * new CBOR data stream from this point, or parse some other data appended to - * the same buffer. - * - * This function may be used even after a parsing error. If that occurred, - * then this function returns a pointer to where the parsing error occurred. - * Note that the error recovery is not precise and the pointer may not indicate - * the exact byte containing bad data. - * - * \sa cbor_value_at_end() - */ - -/** - * \fn bool cbor_value_is_valid(const CborValue *it) - * - * Returns true if the iterator \a it contains a valid value. Invalid iterators - * happen when iteration reaches the end of a container (see \ref - * cbor_value_at_end()) or when a search function resulted in no matches. - * - * \sa cbor_value_advance(), cbor_value_at_end(), cbor_value_get_type() - */ - -/** - * Performs a basic validation of the CBOR stream pointed by \a it and returns - * the error it found. If no error was found, it returns CborNoError and the - * application can iterate over the items with certainty that no other errors - * will appear during parsing. - * - * A basic validation checks for: - * \list - * \li absence of undefined additional information bytes; - * \li well-formedness of all numbers, lengths, and simple values; - * \li string contents match reported sizes; - * \li arrays and maps contain the number of elements they are reported to have; - * \endlist - * - * For further checks, see cbor_value_validate(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance(). - * - * \sa cbor_value_validate(), cbor_value_advance() - */ -CborError cbor_value_validate_basic(const CborValue *it) -{ - CborValue value = *it; - return cbor_value_advance(&value); -} - -/** - * Advances the CBOR value \a it by one fixed-size position. Fixed-size types - * are: integers, tags, simple types (including boolean, null and undefined - * values) and floating point types. - * - * If the type is not of fixed size, this function has undefined behavior. Code - * must be sure that the current type is one of the fixed-size types before - * calling this function. This function is provided because it can guarantee - * that it runs in constant time (O(1)). - * - * If the caller is not able to determine whether the type is fixed or not, code - * can use the cbor_value_advance() function instead. - * - * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance_fixed(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - cbor_assert(is_fixed_type(it->type)); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_internal(it); -} - -static CborError advance_recursive(CborValue *it, int nestingLevel) -{ - CborError err; - CborValue recursed; - - if (is_fixed_type(it->type)) - return advance_internal(it); - - if (!cbor_value_is_container(it)) { - size_t len = SIZE_MAX; - return _cbor_value_copy_string(it, NULL, &len, it); - } - - /* map or array */ - if (nestingLevel == 0) - return CborErrorNestingTooDeep; - - err = cbor_value_enter_container(it, &recursed); - if (err) - return err; - while (!cbor_value_at_end(&recursed)) { - err = advance_recursive(&recursed, nestingLevel - 1); - if (err) - return err; - } - return cbor_value_leave_container(it, &recursed); -} - - -/** - * Advances the CBOR value \a it by one element, skipping over containers. - * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR - * value of any type. However, if the type is a container (map or array) or a - * string with a chunked payload, this function will not run in constant time - * and will recurse into itself (it will run on O(n) time for the number of - * elements or chunks and will use O(n) memory for the number of nested - * containers). - * - * The number of recursions can be limited at compile time to avoid stack - * exhaustion in constrained systems. - * - * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container() - */ -CborError cbor_value_advance(CborValue *it) -{ - cbor_assert(it->type != CborInvalidType); - if (!it->remaining) - return CborErrorAdvancePastEOF; - return advance_recursive(it, CBOR_PARSER_MAX_RECURSIONS); -} - -/** - * \fn bool cbor_value_is_tag(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR tag. - * - * \sa cbor_value_get_tag(), cbor_value_skip_tag() - */ - -/** - * \fn CborError cbor_value_get_tag(const CborValue *value, CborTag *result) - * - * Retrieves the CBOR tag value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a CBOR tag value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_tag is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_tag() - */ - -/** - * Advances the CBOR value \a it until it no longer points to a tag. If \a it is - * already not pointing to a tag, then this function returns it unchanged. - * - * This function does not run in constant time: it will run on O(n) for n being - * the number of tags. It does use constant memory (O(1) memory requirements). - * - * \sa cbor_value_advance_fixed(), cbor_value_advance() - */ -CborError cbor_value_skip_tag(CborValue *it) -{ - while (cbor_value_is_tag(it)) { - CborError err = cbor_value_advance_fixed(it); - if (err) - return err; - } - return CborNoError; -} - -/** - * \fn bool cbor_value_is_container(const CborValue *it) - * - * Returns true if the \a it value is a container and requires recursion in - * order to decode (maps and arrays), false otherwise. - */ - -/** - * Creates a CborValue iterator pointing to the first element of the container - * represented by \a it and saves it in \a recursed. The \a it container object - * needs to be kept and passed again to cbor_value_leave_container() in order - * to continue iterating past this container. - * - * The \a it CborValue iterator must point to a container. - * - * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance() - */ -CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed) -{ - cbor_assert(cbor_value_is_container(it)); - *recursed = *it; - - if (it->flags & CborIteratorFlag_UnknownLength) { - recursed->remaining = UINT32_MAX; - ++recursed->ptr; - } else { - uint64_t len; - CborError err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len); - cbor_assert(err == CborNoError); - - recursed->remaining = (uint32_t)len; - if (recursed->remaining != len || len == UINT32_MAX) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - if (recursed->type == CborMapType) { - /* maps have keys and values, so we need to multiply by 2 */ - if (recursed->remaining > UINT32_MAX / 2) { - /* back track the pointer to indicate where the error occurred */ - recursed->ptr = it->ptr; - return CborErrorDataTooLarge; - } - recursed->remaining *= 2; - } - if (len == 0) { - /* the case of the empty container */ - recursed->type = CborInvalidType; - return CborNoError; - } - } - return preparse_next_value_nodecrement(recursed); -} - -/** - * Updates \a it to point to the next element after the container. The \a - * recursed object needs to point to the element obtained either by advancing - * the last element of the container (via cbor_value_advance(), - * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c - * next pointer from cbor_value_copy_string() or cbor_value_dup_string()). - * - * The \a it and \a recursed parameters must be the exact same as passed to - * cbor_value_enter_container(). - * - * \sa cbor_value_enter_container(), cbor_value_at_end() - */ -CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed) -{ - cbor_assert(cbor_value_is_container(it)); - cbor_assert(recursed->type == CborInvalidType); - it->ptr = recursed->ptr; - return preparse_next_value(it); -} - - -/** - * \fn CborType cbor_value_get_type(const CborValue *value) - * - * Returns the type of the CBOR value that the iterator \a value points to. If - * \a value does not point to a valid value, this function returns \ref - * CborInvalidType. - * - * TinyCBOR also provides functions to test directly if a given CborValue object - * is of a given type, like cbor_value_is_text_string() and cbor_value_is_null(). - * - * \sa cbor_value_is_valid() - */ - -/** - * \fn bool cbor_value_is_null(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR null type. - * - * \sa cbor_value_is_valid(), cbor_value_is_undefined() - */ - -/** - * \fn bool cbor_value_is_undefined(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR undefined type. - * - * \sa cbor_value_is_valid(), cbor_value_is_null() - */ - -/** - * \fn bool cbor_value_is_boolean(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR boolean - * type (true or false). - * - * \sa cbor_value_is_valid(), cbor_value_get_boolean() - */ - -/** - * \fn CborError cbor_value_get_boolean(const CborValue *value, bool *result) - * - * Retrieves the boolean value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to a boolean value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_boolean is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_boolean() - */ - -/** - * \fn bool cbor_value_is_simple_type(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR Simple Type - * type (other than true, false, null and undefined). - * - * \sa cbor_value_is_valid(), cbor_value_get_simple_type() - */ - -/** - * \fn CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) - * - * Retrieves the CBOR Simple Type value that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a simple_type - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_simple_type is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_simple_type() - */ - -/** - * \fn bool cbor_value_is_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR integer - * type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_uint64, cbor_value_get_raw_integer - */ - -/** - * \fn bool cbor_value_is_unsigned_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR unsigned - * integer type (positive values or zero). - * - * \sa cbor_value_is_valid(), cbor_value_get_uint64() - */ - -/** - * \fn bool cbor_value_is_negative_integer(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR negative - * integer type. - * - * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_raw_integer - */ - -/** - * \fn CborError cbor_value_get_int(const CborValue *value, int *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int} are silently truncated to fit. Use - * cbor_value_get_int_checked() if that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_int64(const CborValue *value, int64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Note that this function does not do range-checking: integral values that do - * not fit in a variable of type \c{int64_t} are silently truncated to fit. Use - * cbor_value_get_int64_checked() that is not acceptable. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * \fn CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an unsigned integer - * value, the behavior is undefined, so checking with \ref cbor_value_get_type - * or with \ref cbor_value_is_unsigned_integer is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_unsigned_integer() - */ - -/** - * \fn CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) - * - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * This function is provided because CBOR negative integers can assume values - * that cannot be represented with normal 64-bit integer variables. - * - * If the integer is unsigned (that is, if cbor_value_is_unsigned_integer() - * returns true), then \a result will contain the actual value. If the integer - * is negative, then \a result will contain the absolute value of that integer, - * minus one. That is, \c {actual = -result - 1}. On architectures using two's - * complement for representation of negative integers, it is equivalent to say - * that \a result will contain the bitwise negation of the actual value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() - */ - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int64(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use either - * cbor_value_get_uint64() (if the number is positive) or - * cbor_value_get_raw_integer(). - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64() - */ -CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * The range for int64_t is -2^63 to 2^63-1 (int64_t is required to be - * two's complement, C11 7.20.1.1 paragraph 3), which in CBOR is - * represented the same way, differing only on the "sign bit" (the major - * type). - */ - - if (unlikely(v > (uint64_t)INT64_MAX)) - return CborErrorDataTooLarge; - - *result = v; - if (value->flags & CborIteratorFlag_NegativeInteger) - *result = -*result - 1; - return CborNoError; -} - -/** - * Retrieves the CBOR integer value that \a value points to and stores it in \a - * result. If the iterator \a value does not point to an integer value, the - * behavior is undefined, so checking with \ref cbor_value_get_type or with - * \ref cbor_value_is_integer is recommended. - * - * Unlike \ref cbor_value_get_int(), this function performs a check to see if the - * stored integer fits in \a result without data loss. If the number is outside - * the valid range for the data type, this function returns the recoverable - * error CborErrorDataTooLarge. In that case, use one of the other integer - * functions to obtain the value. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(), - * cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer() - */ -CborError cbor_value_get_int_checked(const CborValue *value, int *result) -{ - uint64_t v; - cbor_assert(cbor_value_is_integer(value)); - v = _cbor_value_extract_int64_helper(value); - - /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): - * "[if] the new type is signed and the value cannot be represented in it; either the - * result is implementation-defined or an implementation-defined signal is raised." - * - * But we can convert from signed to unsigned without fault (paragraph 2). - * - * The range for int is implementation-defined and int is not guaranteed to use - * two's complement representation (although int32_t is). - */ - - if (value->flags & CborIteratorFlag_NegativeInteger) { - if (unlikely(v > (unsigned) -(INT_MIN + 1))) - return CborErrorDataTooLarge; - - *result = (int)v; - *result = -*result - 1; - } else { - if (unlikely(v > (uint64_t)INT_MAX)) - return CborErrorDataTooLarge; - - *result = (int)v; - } - return CborNoError; - -} - -/** - * \fn bool cbor_value_is_length_known(const CborValue *value) - * - * Returns true if the length of this type is known without calculation. That - * is, if the length of this CBOR string, map or array is encoded in the data - * stream, this function returns true. If the length is not encoded, it returns - * false. - * - * If the length is known, code can call cbor_value_get_string_length(), - * cbor_value_get_array_length() or cbor_value_get_map_length() to obtain the - * length. If the length is not known but is necessary, code can use the - * cbor_value_calculate_string_length() function (no equivalent function is - * provided for maps and arrays). - */ - -/** - * \fn bool cbor_value_is_text_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR text - * string. CBOR text strings are UTF-8 encoded and usually contain - * human-readable text. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_text_string(), cbor_value_dup_text_string() - */ - -/** - * \fn bool cbor_value_is_byte_string(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR text - * string. CBOR byte strings are binary data with no specified encoding or - * format. - * - * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), - * cbor_value_copy_byte_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_get_string_length(const CborValue *value, size_t *length) - * - * Extracts the length of the byte or text string that \a value points to and - * stores it in \a result. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * If the length of this string is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * If the length of the string is required but the length was not encoded, use - * cbor_value_calculate_string_length(), but note that that function does not - * run in constant time. - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known(), cbor_value_calculate_string_length() - */ - -/** - * Calculates the length of the byte or text string that \a value points to and - * stores it in \a len. If the iterator \a value does not point to a text - * string or a byte string, the behaviour is undefined, so checking with \ref - * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref - * cbor_value_is_byte_string is recommended. - * - * This function is different from cbor_value_get_string_length() in that it - * calculates the length even for strings sent in chunks. For that reason, this - * function may not run in constant time (it will run in O(n) time on the - * number of chunks). It does use constant memory (O(1)). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known() - */ -CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len) -{ - *len = SIZE_MAX; - return _cbor_value_copy_string(value, NULL, len, NULL); -} - -static inline void prepare_string_iteration(CborValue *it) -{ - if (!cbor_value_is_length_known(it)) { - /* chunked string: we're before the first chunk; - * advance to the first chunk */ - ++it->ptr; - it->flags |= CborIteratorFlag_IteratingStringChunks; - } -} - -CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it) -{ - cbor_assert((it->flags & CborIteratorFlag_IteratingStringChunks) == 0); - prepare_string_iteration(it); - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - return CborNoError; -} - -static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len) -{ - CborError err; - - /* Possible states: - * length known | iterating | meaning - * no | no | before the first chunk of a chunked string - * yes | no | at a non-chunked string - * no | yes | second or later chunk - * yes | yes | after a non-chunked string - */ - if (it->flags & CborIteratorFlag_IteratingStringChunks) { - /* already iterating */ - if (cbor_value_is_length_known(it)) { - /* if the length was known, it wasn't chunked, so finish iteration */ - goto last_chunk; - } - } else { - prepare_string_iteration(it); - } - - /* are we at the end? */ - if (it->ptr == it->parser->end) - return CborErrorUnexpectedEOF; - - if (*it->ptr == BreakByte) { - /* last chunk */ - ++it->ptr; -last_chunk: - *bufferptr = NULL; - *len = 0; - return preparse_next_value(it); - } else if ((uint8_t)(*it->ptr & MajorTypeMask) == it->type) { - err = extract_length(it->parser, &it->ptr, len); - if (err) - return err; - if (*len > (size_t)(it->parser->end - it->ptr)) - return CborErrorUnexpectedEOF; - - *bufferptr = it->ptr; - it->ptr += *len; - } else { - return CborErrorIllegalType; - } - - it->flags |= CborIteratorFlag_IteratingStringChunks; - return CborNoError; -} - -CborError CBOR_INTERNAL_API_CC -_cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, - size_t *len, CborValue *next) -{ - CborValue tmp; - if (!next) - next = &tmp; - *next = *value; - return get_string_chunk(next, bufferptr, len); -} - -/* We return uintptr_t so that we can pass memcpy directly as the iteration - * function. The choice is to optimize for memcpy, which is used in the base - * parser API (cbor_value_copy_string), while memcmp is used in convenience API - * only. */ -typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t); - -static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len) -{ - (void)dest; - (void)src; - (void)len; - return true; -} - -static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len) -{ - return memcmp(s1, (const char *)s2, len) == 0; -} - -static uintptr_t iterate_memcpy(char *dest, const uint8_t *src, size_t len) -{ - return (uintptr_t)memcpy(dest, src, len); -} - -static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen, - bool *result, CborValue *next, IterateFunction func) -{ - CborError err; - CborValue tmp; - size_t total = 0; - const void *ptr; - - cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); - if (!next) - next = &tmp; - *next = *value; - *result = true; - - while (1) { - size_t newTotal; - size_t chunkLen; - err = get_string_chunk(next, &ptr, &chunkLen); - if (err) - return err; - if (!ptr) - break; - - if (unlikely(add_check_overflow(total, chunkLen, &newTotal))) - return CborErrorDataTooLarge; - - if (*result && *buflen >= newTotal) - *result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen); - else - *result = false; - - total = newTotal; - } - - /* is there enough room for the ending NUL byte? */ - if (*result && *buflen > total) { - uint8_t nul[] = { 0 }; - *result = !!func(buffer + total, nul, 1); - } - *buflen = total; - return CborNoError; -} - -/** - * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed to by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of text strings. That byte is - * not included in the returned value of \c{*buflen}. If there was no space for - * the terminating null, no error is returned, so callers must check the value - * of *buflen after the call, before relying on the '\0'; if it has not been - * changed by the call, there is no '\0'-termination on the buffer's contents. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -/** - * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next) - * - * Copies the string pointed by \a value into the buffer provided at \a buffer - * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not - * copy anything and will only update the \a next value. - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If the provided buffer length was too small, this function returns an error - * condition of \ref CborErrorOutOfMemory. If you need to calculate the length - * of the string in order to preallocate a buffer, use - * cbor_value_calculate_string_length(). - * - * On success, this function sets the number of bytes copied to \c{*buflen}. If - * the buffer is large enough, this function will insert a null byte after the - * last copied byte, to facilitate manipulation of null-terminated strings. - * That byte is not included in the returned value of \c{*buflen}. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() - */ - -CborError _cbor_value_copy_string(const CborValue *value, void *buffer, - size_t *buflen, CborValue *next) -{ - bool copied_all; - CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next, - buffer ? iterate_memcpy : iterate_noop); - return err ? err : - copied_all ? CborNoError : CborErrorOutOfMemory; -} - -/** - * Compares the entry \a value with the string \a string and stores the result - * in \a result. If the value is different from \a string \a result will - * contain \c false. - * - * The entry at \a value may be a tagged string. If \a value is not a string or - * a tagged string, the comparison result will be false. - * - * CBOR requires text strings to be encoded in UTF-8, but this function does - * not validate either the strings in the stream or the string \a string to be - * matched. Moreover, comparison is done on strict codepoint comparison, - * without any Unicode normalization. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)). - * - * \sa cbor_value_skip_tag(), cbor_value_copy_text_string() - */ -CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result) -{ - size_t len; - CborValue copy = *value; - CborError err = cbor_value_skip_tag(©); - if (err) - return err; - if (!cbor_value_is_text_string(©)) { - *result = false; - return CborNoError; - } - - len = strlen(string); - return iterate_string_chunks(©, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp); -} - -/** - * \fn bool cbor_value_is_array(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR array. - * - * \sa cbor_value_is_valid(), cbor_value_is_map() - */ - -/** - * \fn CborError cbor_value_get_array_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR array that \a value points to and stores it - * in \a result. If the iterator \a value does not point to a CBOR array, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_array is recommended. - * - * If the length of this array is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * \fn bool cbor_value_is_map(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR map. - * - * \sa cbor_value_is_valid(), cbor_value_is_array() - */ - -/** - * \fn CborError cbor_value_get_map_length(const CborValue *value, size_t *length) - * - * Extracts the length of the CBOR map that \a value points to and stores it in - * \a result. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the length of this map is not encoded in the CBOR data stream, this - * function will return the recoverable error CborErrorUnknownLength. You may - * also check whether that is the case by using cbor_value_is_length_known(). - * - * \note On 32-bit platforms, this function will return error condition of \ref - * CborErrorDataTooLarge if the stream indicates a length that is too big to - * fit in 32-bit. - * - * \sa cbor_value_is_valid(), cbor_value_is_length_known() - */ - -/** - * Attempts to find the value in map \a map that corresponds to the text string - * entry \a string. If the iterator \a value does not point to a CBOR map, the - * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_map is recommended. - * - * If the item is found, it is stored in \a result. If no item is found - * matching the key, then \a result will contain an element of type \ref - * CborInvalidType. Matching is performed using - * cbor_value_text_string_equals(), so tagged strings will also match. - * - * This function has a time complexity of O(n) where n is the number of - * elements in the map to be searched. In addition, this function is has O(n) - * memory requirement based on the number of nested containers (maps or arrays) - * found as elements of this map. - * - * \sa cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance() - */ -CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element) -{ - CborError err; - size_t len = strlen(string); - cbor_assert(cbor_value_is_map(map)); - err = cbor_value_enter_container(map, element); - if (err) - goto error; - - while (!cbor_value_at_end(element)) { - /* find the non-tag so we can compare */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - if (cbor_value_is_text_string(element)) { - bool equals; - size_t dummyLen = len; - err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen, - &equals, element, iterate_memcmp); - if (err) - goto error; - if (equals) - return preparse_value(element); - } else { - /* skip this key */ - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* skip this value */ - err = cbor_value_skip_tag(element); - if (err) - goto error; - err = cbor_value_advance(element); - if (err) - goto error; - } - - /* not found */ - element->type = CborInvalidType; - return CborNoError; - -error: - element->type = CborInvalidType; - return err; -} - -/** - * \fn bool cbor_value_is_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (32-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_float(const CborValue *value, float *result) - * - * Retrieves the CBOR single-precision floating point (32-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a single-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_float is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_float(), cbor_value_get_double() - */ - -/** - * \fn bool cbor_value_is_double(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * double-precision floating point (64-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_float(), cbor_value_is_half_float() - */ - -/** - * \fn CborError cbor_value_get_double(const CborValue *value, float *result) - * - * Retrieves the CBOR double-precision floating point (64-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a double-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_double is recommended. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_double(), cbor_value_get_float() - */ - -/** - * \fn bool cbor_value_is_half_float(const CborValue *value) - * - * Returns true if the iterator \a value is valid and points to a CBOR - * single-precision floating point (16-bit). - * - * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_float() - */ - -/** - * Retrieves the CBOR half-precision floating point (16-bit) value that \a - * value points to and stores it in \a result. If the iterator \a value does - * not point to a half-precision floating point value, the behavior is - * undefined, so checking with \ref cbor_value_get_type or with \ref - * cbor_value_is_half_float is recommended. - * - * Note: since the C language does not have a standard type for half-precision - * floating point, this function takes a \c{void *} as a parameter for the - * storage area, which must be at least 16 bits wide. - * - * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float() - */ -CborError cbor_value_get_half_float(const CborValue *value, void *result) -{ - uint16_t v; - cbor_assert(cbor_value_is_half_float(value)); - - /* size has been computed already */ - v = get16(value->ptr + 1); - memcpy(result, &v, sizeof(v)); - return CborNoError; -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborparser_dup_string.c b/src/cbor/lib/tinycbor/src/cborparser_dup_string.c deleted file mode 100644 index 1360d8b1a..000000000 --- a/src/cbor/lib/tinycbor/src/cborparser_dup_string.c +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef _BSD_SOURCE -#define _BSD_SOURCE 1 -#endif -#ifndef _DEFAULT_SOURCE -#define _DEFAULT_SOURCE 1 -#endif -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "compilersupport_p.h" -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \fn CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a text string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_text_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \note This function does not perform UTF-8 validation on the incoming text - * string. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_text_string(), cbor_value_dup_byte_string() - */ - -/** - * \fn CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next) - * - * Allocates memory for the string pointed by \a value and copies it into this - * buffer. The pointer to the buffer is stored in \a buffer and the number of - * bytes copied is stored in \a buflen (those variables must not be NULL). - * - * If the iterator \a value does not point to a byte string, the behaviour is - * undefined, so checking with \ref cbor_value_get_type or \ref - * cbor_value_is_byte_string is recommended. - * - * If \c malloc returns a NULL pointer, this function will return error - * condition \ref CborErrorOutOfMemory. - * - * On success, \c{*buffer} will contain a valid pointer that must be freed by - * calling \c{free()}. This is the case even for zero-length strings. - * - * The \a next pointer, if not null, will be updated to point to the next item - * after this string. If \a value points to the last item, then \a next will be - * invalid. - * - * This function may not run in constant time (it will run in O(n) time on the - * number of chunks). It requires constant memory (O(1)) in addition to the - * malloc'ed block. - * - * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_byte_string(), cbor_value_dup_text_string() - */ -CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next) -{ - CborError err; - cbor_assert(buffer); - cbor_assert(buflen); - *buflen = SIZE_MAX; - err = _cbor_value_copy_string(value, NULL, buflen, NULL); - if (err) - return err; - - ++*buflen; - *buffer = malloc(*buflen); - if (!*buffer) { - /* out of memory */ - return CborErrorOutOfMemory; - } - err = _cbor_value_copy_string(value, *buffer, buflen, next); - if (err) { - free(*buffer); - return err; - } - return CborNoError; -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cborpretty.c b/src/cbor/lib/tinycbor/src/cborpretty.c deleted file mode 100644 index 2db4b253a..000000000 --- a/src/cbor/lib/tinycbor/src/cborpretty.c +++ /dev/null @@ -1,583 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborPretty Converting CBOR to text - * \brief Group of functions used to convert CBOR to text form. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to a text representation. This module attempts to follow - * the recommendations from RFC 7049 section 6 "Diagnostic Notation", though it - * has a few differences. They are noted below. - * - * TinyCBOR does not provide a way to convert from the text representation back - * to encoded form. To produce a text form meant to be parsed, CborToJson is - * recommended instead. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to text. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The output type produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborToJson, cbor_parser_init() - */ - -/** - * \addtogroup CborPretty - * @{ - *

Text format

- * - * As described in RFC 7049 section 6 "Diagnostic Notation", the format is - * largely borrowed from JSON, but modified to suit CBOR's different data - * types. TinyCBOR makes further modifications to distinguish different, but - * similar values. - * - * CBOR values are currently encoded as follows: - * \par Integrals (unsigned and negative) - * Base-10 (decimal) text representation of the value - * \par Byte strings: - * "h'" followed by the Base16 (hex) representation of the binary data, followed by an ending quote (') - * \par Text strings: - * C-style escaped string in quotes, with C11/C++11 escaping of Unicode codepoints above U+007F. - * \par Tags: - * Tag value, with the tagged value in parentheses. No special encoding of the tagged value is performed. - * \par Simple types: - * "simple(nn)" where \c nn is the simple value - * \par Null: - * \c null - * \par Undefined: - * \c undefined - * \par Booleans: - * \c true or \c false - * \par Floating point: - * If NaN or infinite, the actual words \c NaN or \c infinite. - * Otherwise, the decimal representation with as many digits as necessary to ensure no loss of information. - * By default, float values are suffixed by "f" and half-float values suffixed by "f16" (doubles have no suffix). - * If the CborPrettyNumericEncodingIndicators flag is active, the values instead are encoded following the - * Section 6 recommended encoding indicators: float values are suffixed with "_2" and half-float with "_1". - * A decimal point is always present. - * \par Arrays: - * Comma-separated list of elements, enclosed in square brackets ("[" and "]"). - * \par Maps: - * Comma-separated list of key-value pairs, with the key and value separated - * by a colon (":"), enclosed in curly braces ("{" and "}"). - * - * The CborPrettyFlags enumerator contains flags to control some aspects of the - * encoding: - * \par String fragmentation - * When the CborPrettyShowStringFragments option is active, text and byte - * strings that are transmitted in fragments are shown instead inside - * parentheses ("(" and ")") with no preceding number and each fragment is - * displayed individually. If a tag precedes the string, then the output - * will contain a double set of parentheses. If the option is not active, - * the fragments are merged together and the display will not show any - * difference from a string transmitted with determinate length. - * \par Encoding indicators - * Numbers and lengths in CBOR can be encoded in multiple representations. - * If the CborPrettyIndicateOverlongNumbers option is active, numbers - * and lengths that are transmitted in a longer encoding than necessary - * will be indicated, by appending an underscore ("_") to either the - * number or the opening bracket or brace, followed by a number - * indicating the CBOR additional information: 0 for 1 byte, 1 for 2 - * bytes, 2 for 4 bytes and 3 for 8 bytes. - * If the CborPrettyIndicateIndeterminateLength option is active, maps, - * arrays and strings encoded with indeterminate length will be marked by - * an underscore after the opening bracket or brace or the string (if not - * showing fragments), without a number after it. - */ - -/** - * \enum CborPrettyFlags - * The CborPrettyFlags enum contains flags that control the conversion of CBOR to text format. - * - * \value CborPrettyNumericEncodingIndicators Use numeric encoding indicators instead of textual for float and half-float. - * \value CborPrettyTextualEncodingIndicators Use textual encoding indicators for float ("f") and half-float ("f16"). - * \value CborPrettyIndicateIndeterminateLength (default) Indicate when a map or array has indeterminate length. - * \value CborPrettyIndicateOverlongNumbers Indicate when a number or length was encoded with more bytes than needed. - * \value CborPrettyShowStringFragments If the byte or text string is transmitted in chunks, show each individually. - * \value CborPrettyMergeStringFragment Merge all chunked byte or text strings and display them in a single entry. - * \value CborPrettyDefaultFlags Default conversion flags. - */ - -#ifndef CBOR_NO_FLOATING_POINT -static inline bool convertToUint64(double v, uint64_t *absolute) -{ - double supremum; - v = fabs(v); - - /* C11 standard section 6.3.1.4 "Real floating and integer" says: - * - * 1 When a finite value of real floating type is converted to an integer - * type other than _Bool, the fractional part is discarded (i.e., the - * value is truncated toward zero). If the value of the integral part - * cannot be represented by the integer type, the behavior is undefined. - * - * So we must perform a range check that v <= UINT64_MAX, but we can't use - * UINT64_MAX + 1.0 because the standard continues: - * - * 2 When a value of integer type is converted to a real floating type, if - * the value being converted can be represented exactly in the new type, - * it is unchanged. If the value being converted is in the range of - * values that can be represented but cannot be represented exactly, the - * result is either the nearest higher or nearest lower representable - * value, chosen in an implementation-defined manner. - */ - supremum = -2.0 * INT64_MIN; /* -2 * (- 2^63) == 2^64 */ - if (v >= supremum) - return false; - - /* Now we can convert, these two conversions cannot be UB */ - *absolute = v; - return *absolute == v; -} -#endif - -static void printRecursionLimit(CborStreamFunction stream, void *out) -{ - stream(out, ""); -} - -static CborError hexDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - CborError err = CborNoError; - while (n-- && !err) - err = stream(out, "%02" PRIx8, *buffer++); - - return err; -} - -/* This function decodes buffer as UTF-8 and prints as escaped UTF-16. - * On UTF-8 decoding error, it returns CborErrorInvalidUtf8TextString */ -static CborError utf8EscapedDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - CborError err = CborNoError; - - while (buffer < end && !err) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - - if (uc < 0x80) { - /* single-byte UTF-8 */ - unsigned char escaped = (unsigned char)uc; - if (uc < 0x7f && uc >= 0x20 && uc != '\\' && uc != '"') { - err = stream(out, "%c", (char)uc); - continue; - } - - /* print as an escape sequence */ - switch (uc) { - case '"': - case '\\': - break; - case '\b': - escaped = 'b'; - break; - case '\f': - escaped = 'f'; - break; - case '\n': - escaped = 'n'; - break; - case '\r': - escaped = 'r'; - break; - case '\t': - escaped = 't'; - break; - default: - goto print_utf16; - } - err = stream(out, "\\%c", escaped); - continue; - } - - /* now print the sequence */ - if (uc > 0xffffU) { - /* needs surrogate pairs */ - err = stream(out, "\\u%04" PRIX32 "\\u%04" PRIX32, - (uc >> 10) + 0xd7c0, /* high surrogate */ - (uc % 0x0400) + 0xdc00); - } else { -print_utf16: - /* no surrogate pair needed */ - err = stream(out, "\\u%04" PRIX32, uc); - } - } - return err; -} - -static const char *resolve_indicator(const uint8_t *ptr, const uint8_t *end, int flags) -{ - static const char indicators[8][3] = { - "_0", "_1", "_2", "_3", - "", "", "", /* these are not possible */ - "_" - }; - const char *no_indicator = indicators[5]; /* empty string */ - uint8_t additional_information; - uint8_t expected_information; - uint64_t value; - CborError err; - - if (ptr == end) - return NULL; /* CborErrorUnexpectedEOF */ - - additional_information = (*ptr & SmallValueMask); - if (additional_information < Value8Bit) - return no_indicator; - - /* determine whether to show anything */ - if ((flags & CborPrettyIndicateIndeterminateLength) && - additional_information == IndefiniteLength) - return indicators[IndefiniteLength - Value8Bit]; - if ((flags & CborPrettyIndicateOverlongNumbers) == 0) - return no_indicator; - - err = _cbor_value_extract_number(&ptr, end, &value); - if (err) - return NULL; /* CborErrorUnexpectedEOF */ - - expected_information = Value8Bit - 1; - if (value >= Value8Bit) - ++expected_information; - if (value > 0xffU) - ++expected_information; - if (value > 0xffffU) - ++expected_information; - if (value > 0xffffffffU) - ++expected_information; - return expected_information == additional_information ? - no_indicator : - indicators[additional_information - Value8Bit]; -} - -static const char *get_indicator(const CborValue *it, int flags) -{ - return resolve_indicator(it->ptr, it->parser->end, flags); -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft); -static CborError container_to_pretty(CborStreamFunction stream, void *out, CborValue *it, CborType containerType, - int flags, int recursionsLeft) -{ - const char *comma = ""; - CborError err = CborNoError; - - if (!recursionsLeft) { - printRecursionLimit(stream, out); - return err; /* do allow the dumping to continue */ - } - - while (!cbor_value_at_end(it) && !err) { - err = stream(out, "%s", comma); - comma = ", "; - - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - - if (containerType == CborArrayType) - continue; - - /* map: that was the key, so get the value */ - if (!err) - err = stream(out, ": "); - if (!err) - err = value_to_pretty(stream, out, it, flags, recursionsLeft); - } - return err; -} - -static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft) -{ - CborError err = CborNoError; - CborType type = cbor_value_get_type(it); - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - const char *indicator = get_indicator(it, flags); - const char *space = *indicator ? " " : indicator; - - err = stream(out, "%c%s%s", type == CborArrayType ? '[' : '{', indicator, space); - if (err) - return err; - - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = container_to_pretty(stream, out, &recursed, type, flags, recursionsLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - return stream(out, type == CborArrayType ? "]" : "}"); - } - - case CborIntegerType: { - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - - if (cbor_value_is_unsigned_integer(it)) { - err = stream(out, "%" PRIu64, val); - } else { - /* CBOR stores the negative number X as -1 - X - * (that is, -1 is stored as 0, -2 as 1 and so forth) */ - if (++val) { /* unsigned overflow may happen */ - err = stream(out, "-%" PRIu64, val); - } else { - /* overflown - * 0xffff`ffff`ffff`ffff + 1 = - * 0x1`0000`0000`0000`0000 = 18446744073709551616 (2^64) */ - err = stream(out, "-18446744073709551616"); - } - } - if (!err) - err = stream(out, "%s", get_indicator(it, flags)); - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - bool showingFragments = (flags & CborPrettyShowStringFragments) && !cbor_value_is_length_known(it); - const char *separator = ""; - char close = '\''; - char open[3] = "h'"; - const char *indicator = NULL; - - if (type == CborTextStringType) { - close = open[0] = '"'; - open[1] = '\0'; - } - - if (showingFragments) { - err = stream(out, "(_ "); - if (!err) - err = _cbor_value_prepare_string_iteration(it); - } else { - err = stream(out, "%s", open); - } - - while (!err) { - if (showingFragments || indicator == NULL) { - /* any iteration, except the second for a non-chunked string */ - indicator = resolve_indicator(it->ptr, it->parser->end, flags); - } - - err = _cbor_value_get_string_chunk(it, &ptr, &n, it); - if (!ptr) - break; - - if (!err && showingFragments) - err = stream(out, "%s%s", separator, open); - if (!err) - err = (type == CborByteStringType ? - hexDump(stream, out, ptr, n) : - utf8EscapedDump(stream, out, ptr, n)); - if (!err && showingFragments) { - err = stream(out, "%c%s", close, indicator); - separator = ", "; - } - } - - if (!err) { - if (showingFragments) - err = stream(out, ")"); - else - err = stream(out, "%c%s", close, indicator); - } - return err; - } - - case CborTagType: { - CborTag tag; - cbor_value_get_tag(it, &tag); /* can't fail */ - err = stream(out, "%" PRIu64 "%s(", tag, get_indicator(it, flags)); - if (!err) - err = cbor_value_advance_fixed(it); - if (!err && recursionsLeft) - err = value_to_pretty(stream, out, it, flags, recursionsLeft - 1); - else if (!err) - printRecursionLimit(stream, out); - if (!err) - err = stream(out, ")"); - return err; - } - - case CborSimpleType: { - /* simple types can't fail and can't have overlong encoding */ - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); - err = stream(out, "simple(%" PRIu8 ")", simple_type); - break; - } - - case CborNullType: - err = stream(out, "null"); - break; - - case CborUndefinedType: - err = stream(out, "undefined"); - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - err = stream(out, val ? "true" : "false"); - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - const char *suffix; - double val; - int r; - uint64_t ival; - - if (false) { - float f; - case CborFloatType: - cbor_value_get_float(it, &f); - val = f; - suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f"; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -#ifndef CBOR_NO_HALF_FLOAT_TYPE - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); - suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16"; -#else - (void)f16; - err = CborErrorUnsupportedType; - break; -#endif - } else { - cbor_value_get_double(it, &val); - suffix = ""; - } - - if ((flags & CborPrettyNumericEncodingIndicators) == 0) { - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) - suffix = ""; - } - - if (convertToUint64(val, &ival)) { - /* this double value fits in a 64-bit integer, so show it as such - * (followed by a floating point suffix, to disambiguate) */ - err = stream(out, "%s%" PRIu64 ".%s", val < 0 ? "-" : "", ival, suffix); - } else { - /* this number is definitely not a 64-bit integer */ - err = stream(out, "%." DBL_DECIMAL_DIG_STR "g%s", val, suffix); - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - err = stream(out, "invalid"); - if (err) - return err; - return CborErrorUnknownType; - } - - if (!err) - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Converts the current CBOR type pointed by \a value to its textual - * representation and writes it to the stream by calling the \a streamFunction. - * If an error occurs, this function returns an error code similar to - * \ref CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * \ref CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * The \a streamFunction function will be called with the \a token value as the - * first parameter and a printf-style format string as the second, with a variable - * number of further parameters. - * - * \sa cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags) -{ - return value_to_pretty(streamFunction, token, value, flags, CBOR_PARSER_MAX_RECURSIONS); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborpretty_stdio.c b/src/cbor/lib/tinycbor/src/cborpretty_stdio.c deleted file mode 100644 index 0953e5e8d..000000000 --- a/src/cbor/lib/tinycbor/src/cborpretty_stdio.c +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#include "cbor.h" -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -static CborError cbor_fprintf(void *out, const char *fmt, ...) -{ - int n; - - va_list list; - va_start(list, fmt); - n = vfprintf((FILE *)out, fmt, list); - va_end(list); - - return n < 0 ? CborErrorIO : CborNoError; -} - -/** - * \fn CborError cbor_value_to_pretty(FILE *out, const CborValue *value) - * - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * \sa cbor_value_to_pretty_advance(), cbor_value_to_json_advance() - */ - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty(), cbor_value_to_pretty_stream(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, CborPrettyDefaultFlags); -} - -/** - * Converts the current CBOR type pointed to by \a value to its textual - * representation and writes it to the \a out stream. If an error occurs, this - * function returns an error code similar to CborParsing. - * - * The textual representation can be controlled by the \a flags parameter (see - * CborPrettyFlags for more information). - * - * If no error ocurred, this function advances \a value to the next element. - * Often, concatenating the text representation of multiple elements can be - * done by appending a comma to the output stream in between calls to this - * function. - * - * \sa cbor_value_to_pretty_stream(), cbor_value_to_pretty(), cbor_value_to_json_advance() - */ -CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags) -{ - return cbor_value_to_pretty_stream(cbor_fprintf, out, value, flags); -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/cbortojson.c b/src/cbor/lib/tinycbor/src/cbortojson.c deleted file mode 100644 index ed6a16666..000000000 --- a/src/cbor/lib/tinycbor/src/cbortojson.c +++ /dev/null @@ -1,704 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 -#define _POSIX_C_SOURCE 200809L -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborjson.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" - -#include -#include -#include -#include - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \defgroup CborToJson Converting CBOR to JSON - * \brief Group of functions used to convert CBOR to JSON. - * - * This group contains two functions that can be used to convert a \ref - * CborValue object to an equivalent JSON representation. This module attempts - * to follow the recommendations from RFC 7049 section 4.1 "Converting from - * CBOR to JSON", though it has a few differences. They are noted below. - * - * These functions produce a "minified" JSON output, with no spacing, - * indentation or line breaks. If those are necessary, they need to be applied - * in a post-processing phase. - * - * Note that JSON cannot support all CBOR types with fidelity, so the - * conversion is usually lossy. For that reason, TinyCBOR supports adding a set - * of metadata JSON values that can be used by a JSON-to-CBOR converter to - * restore the original data types. - * - * The TinyCBOR library does not provide a way to convert from JSON - * representation back to encoded form. However, it provides a tool called - * \c json2cbor which can be used for that purpose. That tool supports the - * metadata format that these functions may produce. - * - * Either of the functions in this section will attempt to convert exactly one - * CborValue object to JSON. Those functions may return any error documented - * for the functions for CborParsing. In addition, if the C standard library - * stream functions return with error, the text conversion will return with - * error CborErrorIO. - * - * These functions also perform UTF-8 validation in CBOR text strings. If they - * encounter a sequence of bytes that is not permitted in UTF-8, they will return - * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points - * in UTF-8. - * - * \warning The metadata produced by these functions is not guaranteed to - * remain stable. A future update of TinyCBOR may produce different output for - * the same input and parsers may be unable to handle it. - * - * \sa CborParsing, CborPretty, cbor_parser_init() - */ - -/** - * \addtogroup CborToJson - * @{ - *

Conversion limitations

- * - * When converting from CBOR to JSON, there may be information loss. This - * section lists the possible scenarios. - * - * \par Number precision: - * ALL JSON numbers, due to its JavaScript heritage, are IEEE 754 - * double-precision floating point. This means JSON is not capable of - * representing all integers numbers outside the range [-(253)+1, - * 253-1] and is not capable of representing NaN or infinite. If the - * CBOR data contains a number outside the valid range, the conversion will - * lose precision. If the input was NaN or infinite, the result of the - * conversion will be the JSON null value. In addition, the distinction between - * half-, single- and double-precision is lost. - * - * \par - * If enabled, the original value and original type are stored in the metadata. - * - * \par Non-native types: - * CBOR's type system is richer than JSON's, which means some data values - * cannot be represented when converted to JSON. The conversion silently turns - * them into strings: CBOR simple types become "simple(nn)" where \c nn is the - * simple type's value, with the exception of CBOR undefined, which becomes - * "undefined", while CBOR byte strings are converted to an Base16, Base64, or - * Base64url encoding - * - * \par - * If enabled, the original type is stored in the metadata. - * - * \par Presence of tags: - * JSON has no support for tagged values, so by default tags are dropped when - * converting to JSON. However, if the CborConvertObeyByteStringTags option is - * active (default), then certain known tags are honored and are used to format - * the conversion of the tagged byte string to JSON. - * - * \par - * If the CborConvertTagsToObjects option is active, then the tag and the - * tagged value are converted to a JSON object. Otherwise, if enabled, the - * last (innermost) tag is stored in the metadata. - * - * \par Non-string keys in maps: - * JSON requires all Object keys to be strings, while CBOR does not. By - * default, if a non-string key is found, the conversion fails with error - * CborErrorJsonObjectKeyNotString. If the CborConvertStringifyMapKeys option - * is active, then the conversion attempts to create a string representation - * using CborPretty. Note that the \c json2cbor tool is not able to parse this - * back to the original form. - * - * \par Duplicate keys in maps: - * Neither JSON nor CBOR allow duplicated keys, but current TinyCBOR does not - * validate that this is the case. If there are duplicated keys in the input, - * they will be repeated in the output, which many JSON tools may flag as - * invalid. In addition to that, if the CborConvertStringifyMapKeys option is - * active, it is possible that a non-string key in a CBOR map will be converted - * to a string form that is identical to another key. - * - * \par - * When metadata support is active, the conversion will add extra key-value - * pairs to the JSON output so it can store the metadata. It is possible that - * the keys for the metadata clash with existing keys in the JSON map. - */ - -extern FILE *open_memstream(char **bufptr, size_t *sizeptr); - -enum ConversionStatusFlags { - TypeWasNotNative = 0x100, /* anything but strings, boolean, null, arrays and maps */ - TypeWasTagged = 0x200, - NumberPrecisionWasLost = 0x400, - NumberWasNaN = 0x800, - NumberWasInfinite = 0x1000, - NumberWasNegative = 0x2000, /* only used with NumberWasInifite or NumberWasTooBig */ - - FinalTypeMask = 0xff -}; - -typedef struct ConversionStatus { - CborTag lastTag; - uint64_t originalNumber; - int flags; -} ConversionStatus; - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status); - -static CborError dump_bytestring_base16(char **result, CborValue *it) -{ - static const char characters[] = "0123456789abcdef"; - size_t i; - size_t n = 0; - uint8_t *buffer; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base16 (hex) output is twice as big as our buffer */ - buffer = (uint8_t *)malloc(n * 2 + 1); - *result = (char *)buffer; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, buffer + n - 1, &n, it); - cbor_assert(err == CborNoError); - - for (i = 0; i < n; ++i) { - uint8_t byte = buffer[n + i]; - buffer[2*i] = characters[byte >> 4]; - buffer[2*i + 1] = characters[byte & 0xf]; - } - return CborNoError; -} - -static CborError generic_dump_base64(char **result, CborValue *it, const char alphabet[65]) -{ - size_t n = 0, i; - uint8_t *buffer, *out, *in; - CborError err = cbor_value_calculate_string_length(it, &n); - if (err) - return err; - - /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */ - size_t len = (n + 5) / 3 * 4; - out = buffer = (uint8_t *)malloc(len + 1); - *result = (char *)buffer; - - /* we read our byte string at the tail end of the buffer - * so we can do an in-place conversion while iterating forwards */ - in = buffer + len - n; - - /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ - ++n; - err = cbor_value_copy_byte_string(it, in, &n, it); - cbor_assert(err == CborNoError); - - uint_least32_t val = 0; - for (i = 0; n - i >= 3; i += 3) { - /* read 3 bytes x 8 bits = 24 bits */ - if (false) { -#ifdef __GNUC__ - } else if (i) { - __builtin_memcpy(&val, in + i - 1, sizeof(val)); - val = cbor_ntohl(val); -#endif - } else { - val = (in[i] << 16) | (in[i + 1] << 8) | in[i + 2]; - } - - /* write 4 chars x 6 bits = 24 bits */ - *out++ = alphabet[(val >> 18) & 0x3f]; - *out++ = alphabet[(val >> 12) & 0x3f]; - *out++ = alphabet[(val >> 6) & 0x3f]; - *out++ = alphabet[val & 0x3f]; - } - - /* maybe 1 or 2 bytes left */ - if (n - i) { - /* we can read in[i + 1] even if it's past the end of the string because - * we know (by construction) that it's a NUL byte */ -#ifdef __GNUC__ - uint16_t val16; - __builtin_memcpy(&val16, in + i, sizeof(val16)); - val = cbor_ntohs(val16); -#else - val = (in[i] << 8) | in[i + 1]; -#endif - val <<= 8; - - /* the 65th character in the alphabet is our filler: either '=' or '\0' */ - out[4] = '\0'; - out[3] = alphabet[64]; - if (n - i == 2) { - /* write the third char in 3 chars x 6 bits = 18 bits */ - out[2] = alphabet[(val >> 6) & 0x3f]; - } else { - out[2] = alphabet[64]; /* filler */ - } - out[1] = alphabet[(val >> 12) & 0x3f]; - out[0] = alphabet[(val >> 18) & 0x3f]; - } else { - out[0] = '\0'; - } - - return CborNoError; -} - -static CborError dump_bytestring_base64(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" "="; - return generic_dump_base64(result, it, alphabet); -} - -static CborError dump_bytestring_base64url(char **result, CborValue *it) -{ - static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" - "ghijklmn" "opqrstuv" "wxyz0123" "456789-_"; - return generic_dump_base64(result, it, alphabet); -} - -static CborError add_value_metadata(FILE *out, CborType type, const ConversionStatus *status) -{ - int flags = status->flags; - if (flags & TypeWasTagged) { - /* extract the tagged type, which may be JSON native */ - type = flags & FinalTypeMask; - flags &= ~(FinalTypeMask | TypeWasTagged); - - if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, - flags & ~TypeWasTagged ? "," : "") < 0) - return CborErrorIO; - } - - if (!flags) - return CborNoError; - - /* print at least the type */ - if (fprintf(out, "\"t\":%d", type) < 0) - return CborErrorIO; - - if (flags & NumberWasNaN) - if (fprintf(out, ",\"v\":\"nan\"") < 0) - return CborErrorIO; - if (flags & NumberWasInfinite) - if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0) - return CborErrorIO; - if (flags & NumberPrecisionWasLost) - if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+', - status->originalNumber) < 0) - return CborErrorIO; - if (type == CborSimpleType) - if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0) - return CborErrorIO; - return CborNoError; -} - -static CborError find_tagged_type(CborValue *it, CborTag *tag, CborType *type) -{ - CborError err = CborNoError; - *type = cbor_value_get_type(it); - while (*type == CborTagType) { - cbor_value_get_tag(it, tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - *type = cbor_value_get_type(it); - } - return err; -} - -static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - CborTag tag; - CborError err; - - if (flags & CborConvertTagsToObjects) { - cbor_value_get_tag(it, &tag); /* can't fail */ - err = cbor_value_advance_fixed(it); - if (err) - return err; - - if (fprintf(out, "{\"tag%" PRIu64 "\":", tag) < 0) - return CborErrorIO; - - CborType type = cbor_value_get_type(it); - err = value_to_json(out, it, flags, type, status); - if (err) - return err; - if (flags & CborConvertAddMetadata && status->flags) { - if (fprintf(out, ",\"tag%" PRIu64 "$cbor\":{", tag) < 0 || - add_value_metadata(out, type, status) != CborNoError || - fputc('}', out) < 0) - return CborErrorIO; - } - if (fputc('}', out) < 0) - return CborErrorIO; - status->flags = TypeWasNotNative | CborTagType; - return CborNoError; - } - - CborType type; - err = find_tagged_type(it, &status->lastTag, &type); - if (err) - return err; - tag = status->lastTag; - - /* special handling of byte strings? */ - if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 && - (tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) { - char *str; - char *pre = ""; - - if (tag == CborNegativeBignumTag) { - pre = "~"; - err = dump_bytestring_base64url(&str, it); - } else if (tag == CborExpectedBase64Tag) { - err = dump_bytestring_base64(&str, it); - } else { /* tag == CborExpectedBase16Tag */ - err = dump_bytestring_base16(&str, it); - } - if (err) - return err; - err = fprintf(out, "\"%s%s\"", pre, str) < 0 ? CborErrorIO : CborNoError; - free(str); - status->flags = TypeWasNotNative | TypeWasTagged | CborByteStringType; - return err; - } - - /* no special handling */ - err = value_to_json(out, it, flags, type, status); - status->flags |= TypeWasTagged | type; - return err; -} - -static CborError stringify_map_key(char **key, CborValue *it, int flags, CborType type) -{ - (void)flags; /* unused */ - (void)type; /* unused */ -#ifdef WITHOUT_OPEN_MEMSTREAM - (void)key; /* unused */ - (void)it; /* unused */ - return CborErrorJsonNotImplemented; -#else - size_t size; - - FILE *memstream = open_memstream(key, &size); - if (memstream == NULL) - return CborErrorOutOfMemory; /* could also be EMFILE, but it's unlikely */ - CborError err = cbor_value_to_pretty_advance(memstream, it); - - if (unlikely(fclose(memstream) < 0 || *key == NULL)) - return CborErrorInternalError; - return err; -#endif -} - -static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - while (!cbor_value_at_end(it)) { - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborError err = value_to_json(out, it, flags, cbor_value_get_type(it), status); - if (err) - return err; - } - return CborNoError; -} - -static CborError map_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) -{ - const char *comma = ""; - CborError err; - while (!cbor_value_at_end(it)) { - char *key; - if (fprintf(out, "%s", comma) < 0) - return CborErrorIO; - comma = ","; - - CborType keyType = cbor_value_get_type(it); - if (likely(keyType == CborTextStringType)) { - size_t n = 0; - err = cbor_value_dup_text_string(it, &key, &n, it); - } else if (flags & CborConvertStringifyMapKeys) { - err = stringify_map_key(&key, it, flags, keyType); - } else { - return CborErrorJsonObjectKeyNotString; - } - if (err) - return err; - - /* first, print the key */ - if (fprintf(out, "\"%s\":", key) < 0) { - free(key); - return CborErrorIO; - } - - /* then, print the value */ - CborType valueType = cbor_value_get_type(it); - err = value_to_json(out, it, flags, valueType, status); - - /* finally, print any metadata we may have */ - if (flags & CborConvertAddMetadata) { - if (!err && keyType != CborTextStringType) { - if (fprintf(out, ",\"%s$keycbordump\":true", key) < 0) - err = CborErrorIO; - } - if (!err && status->flags) { - if (fprintf(out, ",\"%s$cbor\":{", key) < 0 || - add_value_metadata(out, valueType, status) != CborNoError || - fputc('}', out) < 0) - err = CborErrorIO; - } - } - - free(key); - if (err) - return err; - } - return CborNoError; -} - -static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status) -{ - CborError err; - status->flags = 0; - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - if (fputc(type == CborArrayType ? '[' : '{', out) < 0) - return CborErrorIO; - - err = (type == CborArrayType) ? - array_to_json(out, &recursed, flags, status) : - map_to_json(out, &recursed, flags, status); - if (err) { - it->ptr = recursed.ptr; - return err; /* parse error */ - } - - if (fputc(type == CborArrayType ? ']' : '}', out) < 0) - return CborErrorIO; - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; /* parse error */ - - status->flags = 0; /* reset, there are never conversion errors for us */ - return CborNoError; - } - - case CborIntegerType: { - double num; /* JS numbers are IEEE double precision */ - uint64_t val; - cbor_value_get_raw_integer(it, &val); /* can't fail */ - num = (double)val; - - if (cbor_value_is_negative_integer(it)) { - num = -num - 1; /* convert to negative */ - if ((uint64_t)(-num - 1) != val) { - status->flags = NumberPrecisionWasLost | NumberWasNegative; - status->originalNumber = val; - } - } else { - if ((uint64_t)num != val) { - status->flags = NumberPrecisionWasLost; - status->originalNumber = val; - } - } - if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */ - return CborErrorIO; - break; - } - - case CborByteStringType: - case CborTextStringType: { - char *str; - if (type == CborByteStringType) { - err = dump_bytestring_base64url(&str, it); - status->flags = TypeWasNotNative; - } else { - size_t n = 0; - err = cbor_value_dup_text_string(it, &str, &n, it); - } - if (err) - return err; - err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError; - free(str); - return err; - } - - case CborTagType: - return tagged_value_to_json(out, it, flags, status); - - case CborSimpleType: { - uint8_t simple_type; - cbor_value_get_simple_type(it, &simple_type); /* can't fail */ - status->flags = TypeWasNotNative; - status->originalNumber = simple_type; - if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0) - return CborErrorIO; - break; - } - - case CborNullType: - if (fprintf(out, "null") < 0) - return CborErrorIO; - break; - - case CborUndefinedType: - status->flags = TypeWasNotNative; - if (fprintf(out, "\"undefined\"") < 0) - return CborErrorIO; - break; - - case CborBooleanType: { - bool val; - cbor_value_get_boolean(it, &val); /* can't fail */ - if (fprintf(out, val ? "true" : "false") < 0) - return CborErrorIO; - break; - } - -#ifndef CBOR_NO_FLOATING_POINT - case CborDoubleType: { - double val; - if (false) { - float f; - case CborFloatType: - status->flags = TypeWasNotNative; - cbor_value_get_float(it, &f); - val = f; - } else if (false) { - uint16_t f16; - case CborHalfFloatType: -# ifndef CBOR_NO_HALF_FLOAT_TYPE - status->flags = TypeWasNotNative; - cbor_value_get_half_float(it, &f16); - val = decode_half(f16); -# else - (void)f16; - err = CborErrorUnsupportedType; - break; -# endif - } else { - cbor_value_get_double(it, &val); - } - - int r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (fprintf(out, "null") < 0) - return CborErrorIO; - status->flags |= r == FP_NAN ? NumberWasNaN : - NumberWasInfinite | (val < 0 ? NumberWasNegative : 0); - } else { - uint64_t ival = (uint64_t)fabs(val); - if ((double)ival == fabs(val)) { - /* print as integer so we get the full precision */ - r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival); - status->flags |= TypeWasNotNative; /* mark this integer number as a double */ - } else { - /* this number is definitely not a 64-bit integer */ - r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val); - } - if (r < 0) - return CborErrorIO; - } - break; - } -#else - case CborDoubleType: - case CborFloatType: - case CborHalfFloatType: - err = CborErrorUnsupportedType; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - - case CborInvalidType: - return CborErrorUnknownType; - } - - return cbor_value_advance_fixed(it); -} - -/** - * \enum CborToJsonFlags - * The CborToJsonFlags enum contains flags that control the conversion of CBOR to JSON. - * - * \value CborConvertAddMetadata Adds metadata to facilitate restoration of the original CBOR data. - * \value CborConvertTagsToObjects Converts CBOR tags to JSON objects - * \value CborConvertIgnoreTags (default) Ignore CBOR tags, except for byte strings - * \value CborConvertObeyByteStringTags (default) Honor formatting of CBOR byte strings if so tagged - * \value CborConvertByteStringsToBase64Url Force the conversion of all CBOR byte strings to Base64url encoding, despite any tags - * \value CborConvertRequireMapStringKeys (default) Require CBOR map keys to be strings, failing the conversion if they are not - * \value CborConvertStringifyMapKeys Convert non-string keys in CBOR maps to a string form - * \value CborConvertDefaultFlags Default conversion flags. - */ - -/** - * \fn CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) - * - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * \sa cbor_value_to_json_advance(), cbor_value_to_pretty() - */ - -/** - * Converts the current CBOR type pointed to by \a value to JSON and writes that - * to the \a out stream. If an error occurs, this function returns an error - * code similar to CborParsing. The \a flags parameter indicates one or more of - * the flags from CborToJsonFlags that control the conversion. - * - * If no error ocurred, this function advances \a value to the next element. - * - * \sa cbor_value_to_json(), cbor_value_to_pretty_advance() - */ -CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) -{ - ConversionStatus status; - return value_to_json(out, value, flags, cbor_value_get_type(value), &status); -} - -#pragma GCC diagnostic pop - -/** @} */ diff --git a/src/cbor/lib/tinycbor/src/cborvalidation.c b/src/cbor/lib/tinycbor/src/cborvalidation.c deleted file mode 100644 index d9445ea27..000000000 --- a/src/cbor/lib/tinycbor/src/cborvalidation.c +++ /dev/null @@ -1,671 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#ifndef __STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - -#include "cbor.h" -#include "cborinternal_p.h" -#include "compilersupport_p.h" -#include "utf8_p.h" - -#include - -#ifndef CBOR_NO_FLOATING_POINT -# include -# include -#endif - - -#ifndef CBOR_PARSER_MAX_RECURSIONS -# define CBOR_PARSER_MAX_RECURSIONS 1024 -#endif - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - -/** - * \addtogroup CborParsing - * @{ - */ - -/** - * \enum CborValidationFlags - * The CborValidationFlags enum contains flags that control the validation of a - * CBOR stream. - * - * \value CborValidateBasic Validates only the syntactic correctedness of the stream. - * \value CborValidateCanonical Validates that the stream is in canonical format, according to - * RFC 7049 section 3.9. - * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10. - * \value CborValidateStrictest Attempt to perform the strictest validation we know of. - * - * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are - * enconded in their shortest form possible. - * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded - * in their shortest form possible. - * \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers - * are in their shortest form possible. - * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses - * indeterminate length encoding. - * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in - * sorted order. - * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique. - * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the - * correct types. This does not validate that the content of - * those types is syntactically correct. For example, this - * option validates that tag 1 (DateTimeString) is used with - * a Text String, but it does not validate that the string is - * a valid date/time representation. - * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately - * encoded in UTF-8. - * \value CborValidateMapKeysAreString Validate that all map keys are text strings. - * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present. - * \value CborValidateNoTags Validate that no tags are used. - * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or - * infinities are allowed). - * \value CborValidateCompleteData Validate that the stream is complete and there is no more data - * in the buffer. - * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered - * with IANA. - * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA. - * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA. - * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags - * are registered with IANA (see below for limitations). - * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA - * (see below for limitations). - * - * \par Simple type registry - * The CBOR specification requires that registration for use of the first 19 - * simple types must be done by way of Standards Action. The rest of the simple - * types only require a specification. The official list can be obtained from - * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml. - * - * \par - * There are no registered simple types recognized by this release of TinyCBOR - * (beyond those defined by RFC 7049). - * - * \par Tag registry - * The CBOR specification requires that registration for use of the first 23 - * tags must be done by way of Standards Action. The next up to tag 255 only - * require a specification. Finally, all other tags can be registered on a - * first-come-first-serve basis. The official list can be ontained from - * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml. - * - * \par - * Given the variability of this list, TinyCBOR cannot recognize all tags - * registered with IANA. Instead, the implementation only recognizes tags - * that are backed by an RFC. - * - * \par - * These are the tags known to the current TinyCBOR release: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TagData ItemSemantics
0UTF-8 text stringStandard date/time string
1integerEpoch-based date/time
2byte stringPositive bignum
3byte stringNegative bignum
4arrayDecimal fraction
5arrayBigfloat
16arrayCOSE Single Recipient Encrypted Data Object (RFC 8152)
17arrayCOSE Mac w/o Recipients Object (RFC 8152)
18arrayCOSE Single Signer Data Object (RFC 8162)
21byte string, array, mapExpected conversion to base64url encoding
22byte string, array, mapExpected conversion to base64 encoding
23byte string, array, mapExpected conversion to base16 encoding
24byte stringEncoded CBOR data item
32UTF-8 text stringURI
33UTF-8 text stringbase64url
34UTF-8 text stringbase64
35UTF-8 text stringRegular expression
36UTF-8 text stringMIME message
96arrayCOSE Encrypted Data Object (RFC 8152)
97arrayCOSE MACed Data Object (RFC 8152)
98arrayCOSE Signed Data Object (RFC 8152)
55799anySelf-describe CBOR
- */ - -struct KnownTagData { uint32_t tag; uint32_t types; }; -static const struct KnownTagData knownTagData[] = { - { 0, (uint32_t)CborTextStringType }, - { 1, (uint32_t)(CborIntegerType+1) }, - { 2, (uint32_t)CborByteStringType }, - { 3, (uint32_t)CborByteStringType }, - { 4, (uint32_t)CborArrayType }, - { 5, (uint32_t)CborArrayType }, - { 16, (uint32_t)CborArrayType }, - { 17, (uint32_t)CborArrayType }, - { 18, (uint32_t)CborArrayType }, - { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, - { 24, (uint32_t)CborByteStringType }, - { 32, (uint32_t)CborTextStringType }, - { 33, (uint32_t)CborTextStringType }, - { 34, (uint32_t)CborTextStringType }, - { 35, (uint32_t)CborTextStringType }, - { 36, (uint32_t)CborTextStringType }, - { 96, (uint32_t)CborArrayType }, - { 97, (uint32_t)CborArrayType }, - { 98, (uint32_t)CborArrayType }, - { 55799, 0U } -}; - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft); - -static inline CborError validate_utf8_string(const void *ptr, size_t n) -{ - const uint8_t *buffer = (const uint8_t *)ptr; - const uint8_t * const end = buffer + n; - while (buffer < end) { - uint32_t uc = get_utf8(&buffer, end); - if (uc == ~0U) - return CborErrorInvalidUtf8TextString; - } - return CborNoError; -} - -static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags) -{ - /* At current time, all known simple types are those from RFC 7049, - * which are parsed by the parser into different CBOR types. - * That means that if we've got here, the type is unknown */ - if (simple_type < 32) - return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError; - return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ? - CborErrorUnknownSimpleType : CborNoError; -} - -static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags) -{ - CborError err = CborNoError; - const uint8_t *ptr = it->ptr; - size_t bytesUsed, bytesNeeded; - uint64_t value; - - if ((flags & CborValidateShortestIntegrals) == 0) - return err; - if (type >= CborHalfFloatType && type <= CborDoubleType) - return err; /* checked elsewhere */ - - err = _cbor_value_extract_number(&ptr, it->parser->end, &value); - if (err) - return err; - - bytesUsed = (size_t)(ptr - it->ptr - 1); - bytesNeeded = 0; - if (value >= Value8Bit) - ++bytesNeeded; - if (value > 0xffU) - ++bytesNeeded; - if (value > 0xffffU) - bytesNeeded += 2; - if (value > 0xffffffffU) - bytesNeeded += 4; - if (bytesNeeded < bytesUsed) - return CborErrorOverlongEncoding; - return CborNoError; -} - -static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft) -{ - CborType type = cbor_value_get_type(it); - const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]); - const struct KnownTagData *tagData = knownTagData; - const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - if (flags & CborValidateNoTags) - return CborErrorExcludedType; - - /* find the tag data, if any */ - for ( ; tagData != knownTagDataEnd; ++tagData) { - if (tagData->tag < tag) - continue; - if (tagData->tag > tag) - tagData = NULL; - break; - } - if (tagData == knownTagDataEnd) - tagData = NULL; - - if (flags & CborValidateNoUnknownTags && !tagData) { - /* tag not found */ - if (flags & CborValidateNoUnknownTagsSA && tag < 24) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256) - return CborErrorUnknownTag; - if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags) - return CborErrorUnknownTag; - } - - if (flags & CborValidateTagUse && tagData && tagData->types) { - uint32_t allowedTypes = tagData->types; - - /* correct Integer so it's not zero */ - if (type == CborIntegerType) - type = (CborType)(type + 1); - - while (allowedTypes) { - if ((uint8_t)(allowedTypes & 0xff) == type) - break; - allowedTypes >>= 8; - } - if (!allowedTypes) - return CborErrorInappropriateTagForType; - } - - return validate_value(it, flags, recursionLeft); -} - -#ifndef CBOR_NO_FLOATING_POINT -static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags) -{ - CborError err; - int r; - double val; - float valf; - uint16_t valf16; - - if (type != CborDoubleType) { - if (type == CborFloatType) { - err = cbor_value_get_float(it, &valf); - val = valf; - } else { -# ifdef CBOR_NO_HALF_FLOAT_TYPE - (void)valf16; - return CborErrorUnsupportedType; -# else - err = cbor_value_get_half_float(it, &valf16); - val = decode_half(valf16); -# endif - } - } else { - err = cbor_value_get_double(it, &val); - } - cbor_assert(err == CborNoError); /* can't fail */ - - r = fpclassify(val); - if (r == FP_NAN || r == FP_INFINITE) { - if (flags & CborValidateFiniteFloatingPoint) - return CborErrorExcludedValue; - if (flags & CborValidateShortestFloatingPoint) { - if (type == CborDoubleType) - return CborErrorOverlongEncoding; -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) - return CborErrorOverlongEncoding; - if (r == FP_NAN && valf16 != 0x7e00) - return CborErrorImproperValue; - if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00) - return CborErrorImproperValue; -# endif - } - } - - if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) { - if (type == CborDoubleType) { - valf = (float)val; - if ((double)valf == val) - return CborErrorOverlongEncoding; - } -# ifndef CBOR_NO_HALF_FLOAT_TYPE - if (type == CborFloatType) { - valf16 = encode_half(valf); - if (valf == decode_half(valf16)) - return CborErrorOverlongEncoding; - } -# endif - } - - return CborNoError; -} -#endif - -static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft) -{ - CborError err; - const uint8_t *previous = NULL; - const uint8_t *previous_end = NULL; - - if (!recursionLeft) - return CborErrorNestingTooDeep; - - while (!cbor_value_at_end(it)) { - const uint8_t *current = cbor_value_get_next_byte(it); - - if (containerType == CborMapType) { - if (flags & CborValidateMapKeysAreString) { - CborType type = cbor_value_get_type(it); - if (type == CborTagType) { - /* skip the tags */ - CborValue copy = *it; - err = cbor_value_skip_tag(©); - if (err) - return err; - type = cbor_value_get_type(©); - } - if (type != CborTextStringType) - return CborErrorMapKeyNotString; - } - } - - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - - if (containerType != CborMapType) - continue; - - if (flags & CborValidateMapIsSorted) { - if (previous) { - uint64_t len1, len2; - const uint8_t *ptr; - - /* extract the two lengths */ - ptr = previous; - _cbor_value_extract_number(&ptr, it->parser->end, &len1); - ptr = current; - _cbor_value_extract_number(&ptr, it->parser->end, &len2); - - if (len1 > len2) - return CborErrorMapNotSorted; - if (len1 == len2) { - size_t bytelen1 = (size_t)(previous_end - previous); - size_t bytelen2 = (size_t)(it->ptr - current); - int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2); - - if (r == 0 && bytelen1 != bytelen2) - r = bytelen1 < bytelen2 ? -1 : +1; - if (r > 0) - return CborErrorMapNotSorted; - if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique) - return CborErrorMapKeysNotUnique; - } - } - - previous = current; - previous_end = it->ptr; - } - - /* map: that was the key, so get the value */ - err = validate_value(it, flags, recursionLeft); - if (err) - return err; - } - return CborNoError; -} - -static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft) -{ - CborError err; - CborType type = cbor_value_get_type(it); - - if (cbor_value_is_length_known(it)) { - err = validate_number(it, type, flags); - if (err) - return err; - } else { - if (flags & CborValidateNoIndeterminateLength) - return CborErrorUnknownLength; - } - - switch (type) { - case CborArrayType: - case CborMapType: { - /* recursive type */ - CborValue recursed; - err = cbor_value_enter_container(it, &recursed); - if (!err) - err = validate_container(&recursed, type, flags, recursionLeft - 1); - if (err) { - it->ptr = recursed.ptr; - return err; - } - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; - return CborNoError; - } - - case CborIntegerType: { - uint64_t val; - err = cbor_value_get_raw_integer(it, &val); - cbor_assert(err == CborNoError); /* can't fail */ - - break; - } - - case CborByteStringType: - case CborTextStringType: { - size_t n = 0; - const void *ptr; - - err = _cbor_value_prepare_string_iteration(it); - if (err) - return err; - - while (1) { - err = validate_number(it, type, flags); - if (err) - return err; - - err = _cbor_value_get_string_chunk(it, &ptr, &n, it); - if (err) - return err; - if (!ptr) - break; - - if (type == CborTextStringType && flags & CborValidateUtf8) { - err = validate_utf8_string(ptr, n); - if (err) - return err; - } - } - - return CborNoError; - } - - case CborTagType: { - CborTag tag; - err = cbor_value_get_tag(it, &tag); - cbor_assert(err == CborNoError); /* can't fail */ - - err = cbor_value_advance_fixed(it); - if (err) - return err; - err = validate_tag(it, tag, flags, recursionLeft - 1); - if (err) - return err; - - return CborNoError; - } - - case CborSimpleType: { - uint8_t simple_type; - err = cbor_value_get_simple_type(it, &simple_type); - cbor_assert(err == CborNoError); /* can't fail */ - err = validate_simple_type(simple_type, flags); - if (err) - return err; - break; - } - - case CborNullType: - case CborBooleanType: - break; - - case CborUndefinedType: - if (flags & CborValidateNoUndefined) - return CborErrorExcludedType; - break; - - case CborHalfFloatType: - case CborFloatType: - case CborDoubleType: { -#ifdef CBOR_NO_FLOATING_POINT - return CborErrorUnsupportedType; -#else - err = validate_floating_point(it, type, flags); - if (err) - return err; - break; -#endif /* !CBOR_NO_FLOATING_POINT */ - } - - case CborInvalidType: - return CborErrorUnknownType; - } - - err = cbor_value_advance_fixed(it); - return err; -} - -/** - * Performs a full validation, controlled by the \a flags options, of the CBOR - * stream pointed by \a it and returns the error it found. If no error was - * found, it returns CborNoError and the application can iterate over the items - * with certainty that no errors will appear during parsing. - * - * If \a flags is CborValidateBasic, the result should be the same as - * cbor_value_validate_basic(). - * - * This function has the same timing and memory requirements as - * cbor_value_advance() and cbor_value_validate_basic(). - * - * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance() - */ -CborError cbor_value_validate(const CborValue *it, uint32_t flags) -{ - CborValue value = *it; - CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS); - if (err) - return err; - if (flags & CborValidateCompleteData && it->ptr != it->parser->end) - return CborErrorGarbageAtEnd; - return CborNoError; -} - -#pragma GCC diagnostic pop - -/** - * @} - */ diff --git a/src/cbor/lib/tinycbor/src/compilersupport_p.h b/src/cbor/lib/tinycbor/src/compilersupport_p.h deleted file mode 100644 index 2b9491d34..000000000 --- a/src/cbor/lib/tinycbor/src/compilersupport_p.h +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef COMPILERSUPPORT_H -#define COMPILERSUPPORT_H - -#include "cbor.h" - -#ifndef _BSD_SOURCE -# define _BSD_SOURCE -#endif -#ifndef _DEFAULT_SOURCE -# define _DEFAULT_SOURCE -#endif -#ifndef assert -# include -#endif -#include -#include -#include - -#ifndef __cplusplus -# include -#endif - -#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410 -# define cbor_static_assert(x) static_assert(x, #x) -#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L) -# define cbor_static_assert(x) _Static_assert(x, #x) -#else -# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1])) -#endif -#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) -/* inline is a keyword */ -#else -/* use the definition from cbor.h */ -# define inline CBOR_INLINE -#endif - -#ifdef NDEBUG -# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0) -#else -# define cbor_assert(cond) assert(cond) -#endif - -#ifndef STRINGIFY -#define STRINGIFY(x) STRINGIFY2(x) -#endif -#define STRINGIFY2(x) #x - -#if !defined(UINT32_MAX) || !defined(INT64_MAX) -/* C89? We can define UINT32_MAX portably, but not INT64_MAX */ -# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX" -#endif - -#ifndef DBL_DECIMAL_DIG -/* DBL_DECIMAL_DIG is C11 */ -# define DBL_DECIMAL_DIG 17 -#endif -#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG) - -#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__) -# define CBOR_INTERNAL_API_CC __attribute__((regparm(3))) -#elif defined(_MSC_VER) && defined(_M_IX86) -# define CBOR_INTERNAL_API_CC __fastcall -#else -# define CBOR_INTERNAL_API_CC -#endif - -#ifndef __has_builtin -# define __has_builtin(x) 0 -#endif - -#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \ - (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32)) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -# define cbor_ntohll __builtin_bswap64 -# define cbor_htonll __builtin_bswap64 -# define cbor_ntohl __builtin_bswap32 -# define cbor_htonl __builtin_bswap32 -# ifdef __INTEL_COMPILER -# define cbor_ntohs _bswap16 -# define cbor_htons _bswap16 -# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16) -# define cbor_ntohs __builtin_bswap16 -# define cbor_htons __builtin_bswap16 -# else -# define cbor_ntohs(x) (((uint16_t)x >> 8) | ((uint16_t)x << 8)) -# define cbor_htons cbor_ntohs -# endif -# else -# define cbor_ntohll -# define cbor_htonll -# define cbor_ntohl -# define cbor_htonl -# define cbor_ntohs -# define cbor_htons -# endif -#elif defined(__sun) -# include -#elif defined(_MSC_VER) -/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */ -# include -# define cbor_ntohll _byteswap_uint64 -# define cbor_htonll _byteswap_uint64 -# define cbor_ntohl _byteswap_ulong -# define cbor_htonl _byteswap_ulong -# define cbor_ntohs _byteswap_ushort -# define cbor_htons _byteswap_ushort -#endif -#ifndef cbor_ntohs -# include -# define cbor_ntohs ntohs -# define cbor_htons htons -#endif -#ifndef cbor_ntohl -# include -# define cbor_ntohl ntohl -# define cbor_htonl htonl -#endif -#ifndef cbor_ntohll -# define cbor_ntohll ntohll -# define cbor_htonll htonll -/* ntohll isn't usually defined */ -# ifndef ntohll -# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ - (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \ - defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__) -# define ntohll -# define htonll -# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ - (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ - (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \ - defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ - defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) -# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32))) -# define htonll ntohll -# else -# error "Unable to determine byte order!" -# endif -# endif -#endif - - -#ifdef __cplusplus -# define CONST_CAST(t, v) const_cast(v) -#else -/* C-style const_cast without triggering a warning with -Wcast-qual */ -# define CONST_CAST(t, v) (t)(uintptr_t)(v) -#endif - -#ifdef __GNUC__ -#ifndef likely -# define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -# define unlikely(x) __builtin_expect(!!(x), 0) -#endif -# define unreachable() __builtin_unreachable() -#elif defined(_MSC_VER) -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() __assume(0) -#else -# define likely(x) (x) -# define unlikely(x) (x) -# define unreachable() do {} while (0) -#endif - -static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r) -{ -#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow) - return __builtin_add_overflow(v1, v2, r); -#else - /* unsigned additions are well-defined */ - *r = v1 + v2; - return v1 > v1 + v2; -#endif -} - -#endif /* COMPILERSUPPORT_H */ - diff --git a/src/cbor/lib/tinycbor/src/open_memstream.c b/src/cbor/lib/tinycbor/src/open_memstream.c deleted file mode 100644 index b3e624d47..000000000 --- a/src/cbor/lib/tinycbor/src/open_memstream.c +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include - -#include - -typedef ssize_t RetType; -typedef size_t LenType; - -#include "compilersupport_p.h" - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" -#pragma GCC diagnostic ignored "-Wreturn-type" -#pragma GCC diagnostic ignored "-Wunused-function" - -struct Buffer -{ - char **ptr; - size_t *len; - size_t alloc; -}; - -static RetType write_to_buffer(void *cookie, const char *data, LenType len) -{ - struct Buffer *b = (struct Buffer *)cookie; - char *ptr = *b->ptr; - size_t newsize; - - errno = EFBIG; - if (unlikely(add_check_overflow(*b->len, len, &newsize))) - return -1; - - if (newsize > b->alloc) { - /* make room */ - size_t newalloc = newsize + newsize / 2 + 1; /* give 50% more room */ - ptr = realloc(ptr, newalloc); - if (ptr == NULL) - return -1; - b->alloc = newalloc; - *b->ptr = ptr; - } - - memcpy(ptr + *b->len, data, len); - *b->len = newsize; - return len; -} - -static int close_buffer(void *cookie) -{ - struct Buffer *b = (struct Buffer *)cookie; - if (*b->ptr) - (*b->ptr)[*b->len] = '\0'; - free(b); - return 0; -} - -FILE *open_memstream(char **bufptr, size_t *lenptr) -{ - struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer)); - if (b == NULL) - return NULL; - b->alloc = 0; - b->len = lenptr; - b->ptr = bufptr; - *bufptr = NULL; - *lenptr = 0; - -#ifdef __APPLE__ - return funopen(b, NULL, write_to_buffer, NULL, close_buffer); -#elif __GLIBC__ - static const cookie_io_functions_t vtable = { - NULL, - write_to_buffer, - NULL, - close_buffer - }; - return fopencookie(b, "w", vtable); -#endif -} - -#pragma GCC diagnostic pop diff --git a/src/cbor/lib/tinycbor/src/tags.txt b/src/cbor/lib/tinycbor/src/tags.txt deleted file mode 100644 index ef78cfb5a..000000000 --- a/src/cbor/lib/tinycbor/src/tags.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Tag number; Tag ID; Applicable types (comma-separated); Semantics -0;DateTimeString;TextString;Standard date/time string -1;UnixTime_t;Integer;Epoch-based date/time -2;PositiveBignum;ByteString;Positive bignum -3;NegativeBignum;ByteString;Negative bignum -4;Decimal;Array;Decimal fraction -5;Bigfloat;Array;Bigfloat -16;COSE_Encrypt0;Array;COSE Single Recipient Encrypted Data Object (RFC 8152) -17;COSE_Mac0;Array;COSE Mac w/o Recipients Object (RFC 8152) -18;COSE_Sign1;Array;COSE Single Signer Data Object (RFC 8162) -21;ExpectedBase64url;ByteString,Array,Map;Expected conversion to base64url encoding -22;ExpectedBase64;ByteString,Array,Map;Expected conversion to base64 encoding -23;ExpectedBase16;ByteString,Array,Map;Expected conversion to base16 encoding -24;EncodedCbor;ByteString;Encoded CBOR data item -32;Url;TextString;URI -33;Base64url;TextString;base64url -34;Base64;TextString;base64 -35;RegularExpression;TextString;Regular expression -36;MimeMessage;TextString;MIME message -96;COSE_Encrypt;Array;COSE Encrypted Data Object (RFC 8152) -97;COSE_Mac;Array;COSE MACed Data Object (RFC 8152) -98;COSE_Sign;Array;COSE Signed Data Object (RFC 8152) -55799;Signature;;Self-describe CBOR diff --git a/src/cbor/lib/tinycbor/src/tinycbor-version.h b/src/cbor/lib/tinycbor/src/tinycbor-version.h deleted file mode 100644 index c57d7fa24..000000000 --- a/src/cbor/lib/tinycbor/src/tinycbor-version.h +++ /dev/null @@ -1,3 +0,0 @@ -#define TINYCBOR_VERSION_MAJOR 0 -#define TINYCBOR_VERSION_MINOR 5 -#define TINYCBOR_VERSION_PATCH 2 diff --git a/src/cbor/lib/tinycbor/src/utf8_p.h b/src/cbor/lib/tinycbor/src/utf8_p.h deleted file mode 100644 index 577e54043..000000000 --- a/src/cbor/lib/tinycbor/src/utf8_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Intel Corporation -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Software. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** -****************************************************************************/ - -#ifndef CBOR_UTF8_H -#define CBOR_UTF8_H - -#include "compilersupport_p.h" - -#include - -static inline uint32_t get_utf8(const uint8_t **buffer, const uint8_t *end) -{ - int charsNeeded; - uint32_t uc, min_uc; - uint8_t b; - ptrdiff_t n = end - *buffer; - if (n == 0) - return ~0U; - - uc = *(*buffer)++; - if (uc < 0x80) { - /* single-byte UTF-8 */ - return uc; - } - - /* multi-byte UTF-8, decode it */ - if (unlikely(uc <= 0xC1)) - return ~0U; - if (uc < 0xE0) { - /* two-byte UTF-8 */ - charsNeeded = 2; - min_uc = 0x80; - uc &= 0x1f; - } else if (uc < 0xF0) { - /* three-byte UTF-8 */ - charsNeeded = 3; - min_uc = 0x800; - uc &= 0x0f; - } else if (uc < 0xF5) { - /* four-byte UTF-8 */ - charsNeeded = 4; - min_uc = 0x10000; - uc &= 0x07; - } else { - return ~0U; - } - - if (n < charsNeeded - 1) - return ~0U; - - /* first continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 2) { - /* second continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - - if (charsNeeded > 3) { - /* third continuation character */ - b = *(*buffer)++; - if ((b & 0xc0) != 0x80) - return ~0U; - uc <<= 6; - uc |= b & 0x3f; - } - } - - /* overlong sequence? surrogate pair? out or range? */ - if (uc < min_uc || uc - 0xd800U < 2048U || uc > 0x10ffff) - return ~0U; - - return uc; -} - -#endif /* CBOR_UTF8_H */ diff --git a/src/property/Property.h b/src/property/Property.h index 7fc1ac846..329d99e32 100644 --- a/src/property/Property.h +++ b/src/property/Property.h @@ -35,7 +35,7 @@ # include #include -#include "../cbor/lib/tinycbor/cbor-lib.h" +#include /****************************************************************************** CONST From 7172d530bea1430e96b7727e325c25fdb314dcb7 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 10:41:45 +0100 Subject: [PATCH 07/40] moving encoder/decoder interfaces into cloudUtils library --- src/interfaces/Decoder.h | 41 ---------------------------------------- src/interfaces/Encoder.h | 40 --------------------------------------- 2 files changed, 81 deletions(-) delete mode 100644 src/interfaces/Decoder.h delete mode 100644 src/interfaces/Encoder.h diff --git a/src/interfaces/Decoder.h b/src/interfaces/Decoder.h deleted file mode 100644 index fc725ec8b..000000000 --- a/src/interfaces/Decoder.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#pragma once - -/****************************************************************************** - * INCLUDES - ******************************************************************************/ - -#include -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class Decoder { -public: - enum Status: uint8_t { - Complete, - InProgress, - Error - }; - - /** - * Decode a buffer into a provided message structure - * @param msg: the message structure that is going to be filled with data provided in the buffer - * @param buf: the incoming buffer that needs to be decoded - * @param len: the length of the incoming buffer, value will be updated with the used len of the buffer - * @return SUCCESS: if the message is decoded correctly - * ERROR: if the message wasn't decoded correctly - */ - virtual Status decode(Message* msg, const uint8_t* const buf, size_t &len) = 0; -}; diff --git a/src/interfaces/Encoder.h b/src/interfaces/Encoder.h deleted file mode 100644 index 38fbe0edd..000000000 --- a/src/interfaces/Encoder.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#pragma once - -/****************************************************************************** - * INCLUDES - ******************************************************************************/ -#include -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class Encoder { -public: - enum Status: uint8_t { - Complete, - InProgress, - Error - }; - - /** - * Encode a message into a buffer in a single shot - * @param msg: the message that needs to be encoded - * @param buf: the buffer the message will be encoded into - * @param len: the length of the provided buffer, value will be updated with the consumed len of the buffer - * @return SUCCESS: if the message is encoded correctly - * ERROR: error during the encoding of the message - */ - virtual Status encode(Message* msg, uint8_t* buf, size_t& len) = 0; -}; From 24553176772fa25e5d31e44cb652ce7dc2f8690e Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 14:12:22 +0100 Subject: [PATCH 08/40] restructuring CBOR.h for cloud utils offload --- src/cbor/CBOR.cpp | 77 ----------------------------------------------- src/cbor/CBOR.h | 16 ++-------- 2 files changed, 2 insertions(+), 91 deletions(-) delete mode 100644 src/cbor/CBOR.cpp diff --git a/src/cbor/CBOR.cpp b/src/cbor/CBOR.cpp deleted file mode 100644 index b043f5a14..000000000 --- a/src/cbor/CBOR.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "CBOR.h" - -/****************************************************************************** - * FUNCTION DEFINITION - ******************************************************************************/ - -CommandId toCommandId(CBORCommandTag tag) { - switch(tag) { - case CBORCommandTag::CBOROtaBeginUp: - return CommandId::OtaBeginUpId; - case CBORCommandTag::CBORThingBeginCmd: - return CommandId::ThingBeginCmdId; - case CBORCommandTag::CBORLastValuesBeginCmd: - return CommandId::LastValuesBeginCmdId; - case CBORCommandTag::CBORDeviceBeginCmd: - return CommandId::DeviceBeginCmdId; - case CBORCommandTag::CBOROtaProgressCmdUp: - return CommandId::OtaProgressCmdUpId; - case CBORCommandTag::CBORTimezoneCommandUp: - return CommandId::TimezoneCommandUpId; - case CBORCommandTag::CBOROtaUpdateCmdDown: - return CommandId::OtaUpdateCmdDownId; - case CBORCommandTag::CBORThingUpdateCmd: - return CommandId::ThingUpdateCmdId; - case CBORCommandTag::CBORThingDetachCmd: - return CommandId::ThingDetachCmdId; - case CBORCommandTag::CBORLastValuesUpdate: - return CommandId::LastValuesUpdateCmdId; - case CBORCommandTag::CBORTimezoneCommandDown: - return CommandId::TimezoneCommandDownId; - default: - return CommandId::UnknownCmdId; - } -} - -CBORCommandTag toCBORCommandTag(CommandId id) { - switch(id) { - case CommandId::OtaBeginUpId: - return CBORCommandTag::CBOROtaBeginUp; - case CommandId::ThingBeginCmdId: - return CBORCommandTag::CBORThingBeginCmd; - case CommandId::LastValuesBeginCmdId: - return CBORCommandTag::CBORLastValuesBeginCmd; - case CommandId::DeviceBeginCmdId: - return CBORCommandTag::CBORDeviceBeginCmd; - case CommandId::OtaProgressCmdUpId: - return CBORCommandTag::CBOROtaProgressCmdUp; - case CommandId::TimezoneCommandUpId: - return CBORCommandTag::CBORTimezoneCommandUp; - case CommandId::OtaUpdateCmdDownId: - return CBORCommandTag::CBOROtaUpdateCmdDown; - case CommandId::ThingUpdateCmdId: - return CBORCommandTag::CBORThingUpdateCmd; - case CommandId::ThingDetachCmdId: - return CBORCommandTag::CBORThingDetachCmd; - case CommandId::LastValuesUpdateCmdId: - return CBORCommandTag::CBORLastValuesUpdate; - case CommandId::TimezoneCommandDownId: - return CBORCommandTag::CBORTimezoneCommandDown; - default: - return CBORCommandTag::CBORUnknownCmdTag; - } -} diff --git a/src/cbor/CBOR.h b/src/cbor/CBOR.h index 7e9a04d97..a5e6bfdcc 100644 --- a/src/cbor/CBOR.h +++ b/src/cbor/CBOR.h @@ -14,12 +14,13 @@ * INCLUDE ******************************************************************************/ #include +#include /****************************************************************************** TYPEDEF ******************************************************************************/ -enum CBORCommandTag: uint64_t { +enum CBORCommandTag: CBORTag { // Commands UP CBOROtaBeginUp = 0x010000, CBORThingBeginCmd = 0x010300, @@ -34,17 +35,4 @@ enum CBORCommandTag: uint64_t { CBORThingDetachCmd = 0x011000, CBORLastValuesUpdate = 0x010600, CBORTimezoneCommandDown = 0x010900, - - // Unknown Command Tag https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml - CBORUnknownCmdTag16b = 0xffff, // invalid tag - CBORUnknownCmdTag32b = 0xffffffff, // invalid tag - CBORUnknownCmdTag64b = 0xffffffffffffffff, // invalid tag - CBORUnknownCmdTag = CBORUnknownCmdTag32b }; - -/****************************************************************************** - * FUNCTION DECLARATION - ******************************************************************************/ - -CommandId toCommandId(CBORCommandTag tag); -CBORCommandTag toCBORCommandTag(CommandId id); From a619b12024021d98c40091f401801ecd69298439 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 14:12:48 +0100 Subject: [PATCH 09/40] splitting Commands definition for utils offload --- src/message/Commands.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/message/Commands.h b/src/message/Commands.h index f0e9a15c9..7e044b7a7 100644 --- a/src/message/Commands.h +++ b/src/message/Commands.h @@ -16,6 +16,7 @@ #include #include +#include /****************************************************************************** * DEFINE @@ -31,10 +32,10 @@ TYPEDEF ******************************************************************************/ -enum CommandId: uint32_t { +enum CommandId: MessageId { /* Device commands */ - DeviceBeginCmdId, + DeviceBeginCmdId = ArduinoIOTCloudStartMessageId, ThingBeginCmdId, ThingUpdateCmdId, ThingDetachCmdId, @@ -60,14 +61,10 @@ enum CommandId: uint32_t { TimezoneCommandDownId, /* Unknown command id */ - UnknownCmdId + UnknownCmdId, }; -struct Command { - CommandId id; -}; - -typedef Command Message; +typedef Message Command; struct DeviceBeginCmd { Command c; @@ -149,7 +146,7 @@ struct TimezoneCommandDown { }; union CommandDown { - struct Command c; + Command c; struct OtaUpdateCmdDown otaUpdateCmdDown; struct ThingUpdateCmd thingUpdateCmd; struct ThingDetachCmd thingDetachCmd; From 7c048bfbec57ed357fd40ab3acec40dcc27611a3 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 14:13:19 +0100 Subject: [PATCH 10/40] implementing cbor message encoder following cloud utils definition --- src/cbor/IoTCloudMessageEncoder.cpp | 161 +++++++++++++++++++++++++ src/cbor/IoTCloudMessageEncoder.h | 75 ++++++++++++ src/cbor/MessageEncoder.cpp | 174 ---------------------------- src/cbor/MessageEncoder.h | 65 ----------- 4 files changed, 236 insertions(+), 239 deletions(-) create mode 100644 src/cbor/IoTCloudMessageEncoder.cpp create mode 100644 src/cbor/IoTCloudMessageEncoder.h delete mode 100644 src/cbor/MessageEncoder.cpp delete mode 100644 src/cbor/MessageEncoder.h diff --git a/src/cbor/IoTCloudMessageEncoder.cpp b/src/cbor/IoTCloudMessageEncoder.cpp new file mode 100644 index 000000000..ed4c6d823 --- /dev/null +++ b/src/cbor/IoTCloudMessageEncoder.cpp @@ -0,0 +1,161 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "CBOREncoder.h" + +#include "IoTCloudMessageEncoder.h" + +/****************************************************************************** + * PUBLIC MEMBER FUNCTIONS + ******************************************************************************/ + + +/****************************************************************************** + PRIVATE MEMBER FUNCTIONS + ******************************************************************************/ + +MessageEncoder::Status OtaBeginCommandEncoder::encode(CborEncoder* encoder, Message *msg) { + OtaBeginUp * otaBeginUp = (OtaBeginUp*) msg; + CborEncoder array_encoder; + + if(cbor_encoder_create_array(encoder, &array_encoder, 1) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_byte_string(&array_encoder, otaBeginUp->params.sha, SHA256_SIZE) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +MessageEncoder::Status ThingBeginCommandEncoder::encode(CborEncoder* encoder, Message *msg) { + ThingBeginCmd * thingBeginCmd = (ThingBeginCmd*) msg; + CborEncoder array_encoder; + + if(cbor_encoder_create_array(encoder, &array_encoder, 1) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_text_stringz(&array_encoder, thingBeginCmd->params.thing_id) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +MessageEncoder::Status LastValuesBeginCommandEncoder::encode(CborEncoder* encoder, Message *msg) { + // This command contains no parameters, it contains just the id of the message + // nothing to perform here + // (void)(encoder); + (void)(msg); + CborEncoder array_encoder; + + /* FIXME We are encoiding an empty array, this could be avoided + if the cloud cbor decode is able to accept an empty array */ + if (cbor_encoder_create_array(encoder, &array_encoder, 0) != CborNoError){ + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +MessageEncoder::Status DeviceBeginCommandEncoder::encode(CborEncoder* encoder, Message *msg) { + DeviceBeginCmd * deviceBeginCmd = (DeviceBeginCmd*) msg; + CborEncoder array_encoder; + + if(cbor_encoder_create_array(encoder, &array_encoder, 1) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_text_stringz(&array_encoder, deviceBeginCmd->params.lib_version) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +MessageEncoder::Status OtaProgressCommandUpEncoder::encode(CborEncoder* encoder, Message *msg) { + OtaProgressCmdUp * ota = (OtaProgressCmdUp*) msg; + CborEncoder array_encoder; + + if(cbor_encoder_create_array(encoder, &array_encoder, 4) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_byte_string(&array_encoder, ota->params.id, ID_SIZE) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_simple_value(&array_encoder, ota->params.state) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_int(&array_encoder, ota->params.state_data) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encode_uint(&array_encoder, ota->params.time) != CborNoError) { + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +MessageEncoder::Status TimezoneCommandUpEncoder::encode(CborEncoder* encoder, Message *msg) { + // This command contains no parameters, it contains just the id of the message + // nothing to perform here + // (void)(encoder); + (void)(msg); + CborEncoder array_encoder; + + /* FIXME We are encoiding an empty array, this could be avoided + if the cloud cbor decode is able to accept an empty array */ + if (cbor_encoder_create_array(encoder, &array_encoder, 0) != CborNoError){ + return MessageEncoder::Status::Error; + } + + if(cbor_encoder_close_container(encoder, &array_encoder) != CborNoError) { + return MessageEncoder::Status::Error; + } + + return MessageEncoder::Status::Complete; +} + +static OtaBeginCommandEncoder otaBeginCommandEncoder; +static ThingBeginCommandEncoder thingBeginCommandEncoder; +static LastValuesBeginCommandEncoder lastValuesBeginCommandEncoder; +static DeviceBeginCommandEncoder deviceBeginCommandEncoder; +static OtaProgressCommandUpEncoder otaProgressCommandUpEncoder; +static TimezoneCommandUpEncoder timezoneCommandUpEncoder; diff --git a/src/cbor/IoTCloudMessageEncoder.h b/src/cbor/IoTCloudMessageEncoder.h new file mode 100644 index 000000000..99922bc59 --- /dev/null +++ b/src/cbor/IoTCloudMessageEncoder.h @@ -0,0 +1,75 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_CBOR_MESSAGE_ENCODER_H_ +#define ARDUINO_CBOR_MESSAGE_ENCODER_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include "./CBOR.h" +#include +#include "message/Commands.h" + +/****************************************************************************** + * CLASS DECLARATION + ******************************************************************************/ + +class OtaBeginCommandEncoder: public CBORMessageEncoderInterface { +public: + OtaBeginCommandEncoder() + : CBORMessageEncoderInterface(CBOROtaBeginUp, OtaBeginUpId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + +class ThingBeginCommandEncoder: public CBORMessageEncoderInterface { +public: + ThingBeginCommandEncoder() + : CBORMessageEncoderInterface(CBORThingBeginCmd, ThingBeginCmdId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + +class LastValuesBeginCommandEncoder: public CBORMessageEncoderInterface { +public: + LastValuesBeginCommandEncoder() + : CBORMessageEncoderInterface(CBORLastValuesBeginCmd, LastValuesBeginCmdId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + +class DeviceBeginCommandEncoder: public CBORMessageEncoderInterface { +public: + DeviceBeginCommandEncoder() + : CBORMessageEncoderInterface(CBORDeviceBeginCmd, DeviceBeginCmdId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + +class OtaProgressCommandUpEncoder: public CBORMessageEncoderInterface { +public: + OtaProgressCommandUpEncoder() + : CBORMessageEncoderInterface(CBOROtaProgressCmdUp, OtaProgressCmdUpId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + +class TimezoneCommandUpEncoder: public CBORMessageEncoderInterface { +public: + TimezoneCommandUpEncoder() + : CBORMessageEncoderInterface(CBORTimezoneCommandUp, TimezoneCommandUpId) {} +protected: + MessageEncoder::Status encode(CborEncoder* encoder, Message *msg) override; +}; + + +#endif /* ARDUINO_CBOR_MESSAGE_ENCODER_H_ */ diff --git a/src/cbor/MessageEncoder.cpp b/src/cbor/MessageEncoder.cpp deleted file mode 100644 index 56bae9ef2..000000000 --- a/src/cbor/MessageEncoder.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include "CBOREncoder.h" - -#undef max -#undef min -#include -#include - -#include "MessageEncoder.h" - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -Encoder::Status CBORMessageEncoder::encode(Message * message, uint8_t * data, size_t& len) -{ - EncoderState current_state = EncoderState::EncodeTag, - next_state = EncoderState::Error; - - CborEncoder encoder; - CborEncoder arrayEncoder; - - cbor_encoder_init(&encoder, data, len, 0); - - while (current_state != EncoderState::Complete) { - - switch (current_state) { - case EncoderState::EncodeTag : next_state = handle_EncodeTag(&encoder, message); break; - case EncoderState::EncodeArray : next_state = handle_EncodeArray(&encoder, &arrayEncoder, message); break; - case EncoderState::EncodeParam : next_state = handle_EncodeParam(&arrayEncoder, message); break; - case EncoderState::CloseArray : next_state = handle_CloseArray(&encoder, &arrayEncoder); break; - case EncoderState::Complete : /* Nothing to do */ break; - case EncoderState::MessageNotSupported : - case EncoderState::Error : return Encoder::Status::Error; - } - - current_state = next_state; - } - - len = cbor_encoder_get_buffer_size(&encoder, data); - - return Encoder::Status::Complete; -} - -/****************************************************************************** - PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeTag(CborEncoder * encoder, Message * message) -{ - CborTag commandTag = toCBORCommandTag(message->id); - if (commandTag == CBORCommandTag::CBORUnknownCmdTag16b || - commandTag == CBORCommandTag::CBORUnknownCmdTag32b || - commandTag == CBORCommandTag::CBORUnknownCmdTag64b || - cbor_encode_tag(encoder, commandTag) != CborNoError) { - return EncoderState::Error; - } - - return EncoderState::EncodeArray; -} - -CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeArray(CborEncoder * encoder, CborEncoder * array_encoder, Message * message) -{ - // Set array size based on the message id - size_t array_size = 0; - switch (message->id) - { - case CommandId::OtaBeginUpId: - array_size = 1; - break; - case CommandId::ThingBeginCmdId: - array_size = 1; - break; - case CommandId::DeviceBeginCmdId: - array_size = 1; - break; - case CommandId::LastValuesBeginCmdId: - break; - case CommandId::OtaProgressCmdUpId: - array_size = 4; - break; - case CommandId::TimezoneCommandUpId: - break; - default: - return EncoderState::MessageNotSupported; - } - - // Start an array with fixed width based on message type - if (cbor_encoder_create_array(encoder, array_encoder, array_size) != CborNoError){ - return EncoderState::Error; - } - - return EncoderState::EncodeParam; -} - -CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_EncodeParam(CborEncoder * array_encoder, Message * message) -{ - CborError error = CborNoError; - switch (message->id) - { - case CommandId::OtaBeginUpId: - error = CBORMessageEncoder::encodeOtaBeginUp(array_encoder, message); - break; - case CommandId::ThingBeginCmdId: - error = CBORMessageEncoder::encodeThingBeginCmd(array_encoder, message); - break; - case CommandId::DeviceBeginCmdId: - error = CBORMessageEncoder::encodeDeviceBeginCmd(array_encoder, message); - break; - case CommandId::LastValuesBeginCmdId: - break; - case CommandId::OtaProgressCmdUpId: - error = CBORMessageEncoder::encodeOtaProgressCmdUp(array_encoder, message); - break; - case CommandId::TimezoneCommandUpId: - break; - default: - return EncoderState::MessageNotSupported; - } - - return (error != CborNoError) ? EncoderState::Error : EncoderState::CloseArray; -} - -CBORMessageEncoder::EncoderState CBORMessageEncoder::handle_CloseArray(CborEncoder * encoder, CborEncoder * array_encoder) -{ - CborError error = cbor_encoder_close_container(encoder, array_encoder); - - return (error != CborNoError) ? EncoderState::Error : EncoderState::Complete; -} - -// Message specific encoders -CborError CBORMessageEncoder::encodeOtaBeginUp(CborEncoder * array_encoder, Message * message) -{ - OtaBeginUp * otaBeginUp = (OtaBeginUp *) message; - CHECK_CBOR(cbor_encode_byte_string(array_encoder, otaBeginUp->params.sha, SHA256_SIZE)); - return CborNoError; -} - -CborError CBORMessageEncoder::encodeThingBeginCmd(CborEncoder * array_encoder, Message * message) -{ - ThingBeginCmd * thingBeginCmd = (ThingBeginCmd *) message; - CHECK_CBOR(cbor_encode_text_stringz(array_encoder, thingBeginCmd->params.thing_id)); - return CborNoError; -} - -CborError CBORMessageEncoder::encodeDeviceBeginCmd(CborEncoder * array_encoder, Message * message) -{ - DeviceBeginCmd * deviceBeginCmd = (DeviceBeginCmd *) message; - CHECK_CBOR(cbor_encode_text_stringz(array_encoder, deviceBeginCmd->params.lib_version)); - return CborNoError; -} - -CborError CBORMessageEncoder::encodeOtaProgressCmdUp(CborEncoder * array_encoder, Message * message) -{ - OtaProgressCmdUp * ota = (OtaProgressCmdUp *)message; - CHECK_CBOR(cbor_encode_byte_string(array_encoder, ota->params.id, ID_SIZE)); - CHECK_CBOR(cbor_encode_simple_value(array_encoder, ota->params.state)); - CHECK_CBOR(cbor_encode_int(array_encoder, ota->params.state_data)); - CHECK_CBOR(cbor_encode_uint(array_encoder, ota->params.time)); - return CborNoError; -} diff --git a/src/cbor/MessageEncoder.h b/src/cbor/MessageEncoder.h deleted file mode 100644 index 81ae94ce8..000000000 --- a/src/cbor/MessageEncoder.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#ifndef ARDUINO_CBOR_MESSAGE_ENCODER_H_ -#define ARDUINO_CBOR_MESSAGE_ENCODER_H_ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include - -#undef max -#undef min -#include - -#include "CBOR.h" -#include "../interfaces/Encoder.h" -#include - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class CBORMessageEncoder: public Encoder -{ - -public: - CBORMessageEncoder() { } - CBORMessageEncoder(CborEncoder const &) { } - Encoder::Status encode(Message * message, uint8_t * data, size_t& len); - -private: - - enum class EncoderState - { - EncodeTag, - EncodeArray, - EncodeParam, - CloseArray, - MessageNotSupported, - Complete, - Error - }; - - EncoderState handle_EncodeTag(CborEncoder * encoder, Message * message); - EncoderState handle_EncodeArray(CborEncoder * encoder, CborEncoder * array_encoder, Message * message); - EncoderState handle_EncodeParam(CborEncoder * array_encoder, Message * message); - EncoderState handle_CloseArray(CborEncoder * encoder, CborEncoder * array_encoder); - - // Message specific encoders - CborError encodeThingBeginCmd(CborEncoder * array_encoder, Message * message); - CborError encodeOtaBeginUp(CborEncoder * array_encoder, Message * message); - CborError encodeDeviceBeginCmd(CborEncoder * array_encoder, Message * message); - CborError encodeOtaProgressCmdUp(CborEncoder * array_encoder, Message * message); -}; - -#endif /* ARDUINO_CBOR_MESSAGE_ENCODER_H_ */ From 78507dfd3d6b0dde8dc1e5b6b3c7759b09adf6ad Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 30 Jan 2025 15:27:34 +0100 Subject: [PATCH 11/40] implementing cbor message decoder following cloud utils definition --- src/cbor/IoTCloudMessageDecoder.cpp | 165 +++++++++++++++++++ src/cbor/IoTCloudMessageDecoder.h | 66 ++++++++ src/cbor/MessageDecoder.cpp | 244 ---------------------------- src/cbor/MessageDecoder.h | 75 --------- 4 files changed, 231 insertions(+), 319 deletions(-) create mode 100644 src/cbor/IoTCloudMessageDecoder.cpp create mode 100644 src/cbor/IoTCloudMessageDecoder.h delete mode 100644 src/cbor/MessageDecoder.cpp delete mode 100644 src/cbor/MessageDecoder.h diff --git a/src/cbor/IoTCloudMessageDecoder.cpp b/src/cbor/IoTCloudMessageDecoder.cpp new file mode 100644 index 000000000..e25962219 --- /dev/null +++ b/src/cbor/IoTCloudMessageDecoder.cpp @@ -0,0 +1,165 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include + +#include "IoTCloudMessageDecoder.h" +#include + +static inline bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) { + if (cbor_value_is_text_string(param)) { + // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string + if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { + return true; + } + } + + return false; +} + +static inline size_t copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) { + if (cbor_value_is_byte_string(param)) { + // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string + if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { + return dest_size; + } + } + + return 0; +} + +/****************************************************************************** + MESSAGE DECODE FUNCTIONS + ******************************************************************************/ + +MessageDecoder::Status ThingUpdateCommandDecoder::decode(CborValue* iter, Message *msg) { + ThingUpdateCmd * thingCommand = (ThingUpdateCmd *) msg; + + // Message is composed of a single parameter, a string (thing_id) + if (!copyCBORStringToArray(iter, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { + return MessageDecoder::Status::Error; + } + + return MessageDecoder::Status::Complete; +} + +MessageDecoder::Status ThingDetachCommandDecoder::decode(CborValue* iter, Message *msg) { + ThingDetachCmd * thingCommand = (ThingDetachCmd *) msg; + + // Message is composed of a single parameter, a string (thing_id) + if (!copyCBORStringToArray(iter, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { + return MessageDecoder::Status::Error; + } + + return MessageDecoder::Status::Complete; +} + +MessageDecoder::Status TimezoneCommandDownDecoder::decode(CborValue* iter, Message *msg) { + TimezoneCommandDown * setTz = (TimezoneCommandDown *) msg; + + // Message is composed of 2 parameters, offset 32-bit signed integer and until 32-bit unsigned integer + // Get offset + if (!cbor_value_is_integer(iter)) { + return MessageDecoder::Status::Error; + } + + int64_t val = 0; + if (cbor_value_get_int64(iter, &val) != CborNoError) { + return MessageDecoder::Status::Error; + } + + setTz->params.offset = static_cast(val); + + // Next + if (cbor_value_advance(iter) != CborNoError) { + return MessageDecoder::Status::Error; + } + + // Get until + if (!cbor_value_is_integer(iter)) { + return MessageDecoder::Status::Error; + } + + uint64_t val1 = 0; + if (cbor_value_get_uint64(iter, &val1) != CborNoError) { + return MessageDecoder::Status::Error; + } + + setTz->params.until = static_cast(val1); + + return MessageDecoder::Status::Complete; +} + +MessageDecoder::Status LastValuesUpdateCommandDecoder::decode(CborValue* iter, Message *msg) { + LastValuesUpdateCmd * setLv = (LastValuesUpdateCmd *) msg; + + if(!cbor_value_is_byte_string(iter)) { + return MessageDecoder::Status::Error; + } + + // Cortex M0 is not able to assign a value to pointed memory that is not 32bit aligned + // we use a support variable to cope with that + size_t s; + + // NOTE: cbor_value_dup_byte_string calls malloc and assigns it to the second parameter of the call, + // free must be called. Free has to be called only if decode succeeds. + // Read tinyCbor documentation for more information. + if (cbor_value_dup_byte_string(iter, &setLv->params.last_values, &s, NULL) != CborNoError) { + return MessageDecoder::Status::Error; + } + + setLv->params.length = s; + + return MessageDecoder::Status::Complete; +} + +MessageDecoder::Status OtaUpdateCommandDecoder::decode(CborValue* iter, Message *msg) { + CborError error = CborNoError; + OtaUpdateCmdDown * ota = (OtaUpdateCmdDown *) msg; + + // Message is composed 4 parameters: id, url, initialSha, finalSha + if (!copyCBORByteToArray(iter, ota->params.id, sizeof(ota->params.id))) { + return MessageDecoder::Status::Error; + } + + error = cbor_value_advance(iter); + + if ((error != CborNoError) || !copyCBORStringToArray(iter, ota->params.url, sizeof(ota->params.url))) { + return MessageDecoder::Status::Error; + } + + error = cbor_value_advance(iter); + + if ((error != CborNoError) || + copyCBORByteToArray(iter, ota->params.initialSha256, + sizeof(ota->params.initialSha256)) != sizeof(ota->params.initialSha256)) { + return MessageDecoder::Status::Error; + } + + error = cbor_value_advance(iter); + + if ((error != CborNoError) || + copyCBORByteToArray(iter, ota->params.finalSha256, + sizeof(ota->params.finalSha256)) != sizeof(ota->params.finalSha256)) { + return MessageDecoder::Status::Error; + } + + return MessageDecoder::Status::Complete; +} + +static OtaUpdateCommandDecoder otaUpdateCommandDecoder; +static ThingUpdateCommandDecoder thingUpdateCommandDecoder; +static ThingDetachCommandDecoder thingDetachCommandDecoder; +static LastValuesUpdateCommandDecoder lastValuesUpdateCommandDecoder; +static TimezoneCommandDownDecoder timezoneCommandDownDecoder; diff --git a/src/cbor/IoTCloudMessageDecoder.h b/src/cbor/IoTCloudMessageDecoder.h new file mode 100644 index 000000000..4b444f5c8 --- /dev/null +++ b/src/cbor/IoTCloudMessageDecoder.h @@ -0,0 +1,66 @@ +/* + This file is part of the ArduinoIoTCloud library. + + Copyright (c) 2024 Arduino SA + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ARDUINO_CBOR_MESSAGE_DECODER_H_ +#define ARDUINO_CBOR_MESSAGE_DECODER_H_ + +/****************************************************************************** + INCLUDE + ******************************************************************************/ + +#include "./CBOR.h" +#include +#include "message/Commands.h" + +/****************************************************************************** + CLASS DECLARATION + ******************************************************************************/ + +class OtaUpdateCommandDecoder: public CBORMessageDecoderInterface { +public: + OtaUpdateCommandDecoder() + : CBORMessageDecoderInterface(CBOROtaUpdateCmdDown, OtaUpdateCmdDownId) {} +protected: + MessageDecoder::Status decode(CborValue* iter, Message *msg) override; +}; + +class ThingUpdateCommandDecoder: public CBORMessageDecoderInterface { +public: + ThingUpdateCommandDecoder() + : CBORMessageDecoderInterface(CBORThingUpdateCmd, ThingUpdateCmdId) {} +protected: + MessageDecoder::Status decode(CborValue* iter, Message *msg) override; +}; + +class ThingDetachCommandDecoder: public CBORMessageDecoderInterface { +public: + ThingDetachCommandDecoder() + : CBORMessageDecoderInterface(CBORThingDetachCmd, ThingDetachCmdId) {} +protected: + MessageDecoder::Status decode(CborValue* iter, Message *msg) override; +}; + +class LastValuesUpdateCommandDecoder: public CBORMessageDecoderInterface { +public: + LastValuesUpdateCommandDecoder() + : CBORMessageDecoderInterface(CBORLastValuesUpdate, LastValuesUpdateCmdId) {} +protected: + MessageDecoder::Status decode(CborValue* iter, Message *msg) override; +}; + +class TimezoneCommandDownDecoder: public CBORMessageDecoderInterface { +public: + TimezoneCommandDownDecoder() + : CBORMessageDecoderInterface(CBORTimezoneCommandDown, TimezoneCommandDownId) {} +protected: + MessageDecoder::Status decode(CborValue* iter, Message *msg) override; +}; + +#endif /* ARDUINO_CBOR_MESSAGE_DECODER_H_ */ diff --git a/src/cbor/MessageDecoder.cpp b/src/cbor/MessageDecoder.cpp deleted file mode 100644 index 7c3e9a215..000000000 --- a/src/cbor/MessageDecoder.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include - -#undef max -#undef min -#include - -#include "MessageDecoder.h" -#include - -/****************************************************************************** - PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -Decoder::Status CBORMessageDecoder::decode(Message * message, uint8_t const * const payload, size_t& length) -{ - CborValue main_iter, array_iter; - CborTag tag; - CborParser parser; - - if (cbor_parser_init(payload, length, 0, &parser, &main_iter) != CborNoError) - return Decoder::Status::Error; - - if (main_iter.type != CborTagType) - return Decoder::Status::Error; - - if (cbor_value_get_tag(&main_iter, &tag) == CborNoError) { - message->id = toCommandId(CBORCommandTag(tag)); - } - - if (cbor_value_advance(&main_iter) != CborNoError) { - return Decoder::Status::Error; - } - - ArrayParserState current_state = ArrayParserState::EnterArray, - next_state = ArrayParserState::Error; - - while (current_state != ArrayParserState::Complete) { - switch (current_state) { - case ArrayParserState::EnterArray : next_state = handle_EnterArray(&main_iter, &array_iter); break; - case ArrayParserState::ParseParam : next_state = handle_Param(&array_iter, message); break; - case ArrayParserState::LeaveArray : next_state = handle_LeaveArray(&main_iter, &array_iter); break; - case ArrayParserState::Complete : return Decoder::Status::Complete; - case ArrayParserState::MessageNotSupported : return Decoder::Status::Error; - case ArrayParserState::Error : return Decoder::Status::Error; - } - - current_state = next_state; - } - - return Decoder::Status::Complete; -} - -/****************************************************************************** - PRIVATE MEMBER FUNCTIONS - ******************************************************************************/ - -bool copyCBORStringToArray(CborValue * param, char * dest, size_t dest_size) { - if (cbor_value_is_text_string(param)) { - // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string - if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { - return true; - } - } - - return false; -} - -// FIXME dest_size should be also returned, the copied byte array can have a different size from the starting one -// for the time being we need this on SHA256 only -bool copyCBORByteToArray(CborValue * param, uint8_t * dest, size_t dest_size) { - if (cbor_value_is_byte_string(param)) { - // NOTE: keep in mind that _cbor_value_copy_string tries to put a \0 at the end of the string - if(_cbor_value_copy_string(param, dest, &dest_size, NULL) == CborNoError) { - return true; - } - } - - return false; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_EnterArray(CborValue * main_iter, CborValue * array_iter) { - ArrayParserState next_state = ArrayParserState::Error; - if (cbor_value_get_type(main_iter) == CborArrayType) { - if (cbor_value_enter_container(main_iter, array_iter) == CborNoError) { - next_state = ArrayParserState::ParseParam; - } - } - - return next_state; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_LeaveArray(CborValue * main_iter, CborValue * array_iter) { - // Advance to the next parameter (the last one in the array) - if (cbor_value_advance(array_iter) == CborNoError) { - // Leave the array - if (cbor_value_leave_container(main_iter, array_iter) == CborNoError) { - return ArrayParserState::Complete; - } - } - - return ArrayParserState::Error; -} - -/****************************************************************************** - MESSAGE DECODE FUNCTIONS - ******************************************************************************/ - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingUpdateCmd(CborValue * param, Message * message) { - ThingUpdateCmd * thingCommand = (ThingUpdateCmd *) message; - - // Message is composed of a single parameter, a string (thing_id) - if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { - return ArrayParserState::Error; - } - - return ArrayParserState::LeaveArray; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeThingDetachCmd(CborValue * param, Message * message) { - ThingDetachCmd * thingCommand = (ThingDetachCmd *) message; - - // Message is composed of a single parameter, a string (thing_id) - if (!copyCBORStringToArray(param, thingCommand->params.thing_id, sizeof(thingCommand->params.thing_id))) { - return ArrayParserState::Error; - } - - return ArrayParserState::LeaveArray; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeTimezoneCommandDown(CborValue * param, Message * message) { - TimezoneCommandDown * setTz = (TimezoneCommandDown *) message; - - // Message is composed of 2 parameters, offset 32-bit signed integer and until 32-bit unsigned integer - // Get offset - if (cbor_value_is_integer(param)) { - int64_t val = 0; - if (cbor_value_get_int64(param, &val) == CborNoError) { - setTz->params.offset = static_cast(val); - } - } - - // Next - if (cbor_value_advance(param) != CborNoError) { - return ArrayParserState::Error; - } - - // Get until - if (cbor_value_is_integer(param)) { - uint64_t val = 0; - if (cbor_value_get_uint64(param, &val) == CborNoError) { - setTz->params.until = static_cast(val); - } - } - - return ArrayParserState::LeaveArray; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeLastValuesUpdateCmd(CborValue * param, Message * message) { - LastValuesUpdateCmd * setLv = (LastValuesUpdateCmd *) message; - - // Message is composed by a single parameter, a variable length byte array. - if (cbor_value_is_byte_string(param)) { - // Cortex M0 is not able to assign a value to pointed memory that is not 32bit aligned - // we use a support variable to cope with that - size_t s; - if (cbor_value_dup_byte_string(param, &setLv->params.last_values, &s, NULL) != CborNoError) { - return ArrayParserState::Error; - } - - setLv->params.length = s; - } - - return ArrayParserState::LeaveArray; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::decodeOtaUpdateCmdDown(CborValue * param, Message * message) { - CborError error = CborNoError; - OtaUpdateCmdDown * ota = (OtaUpdateCmdDown *) message; - - // Message is composed 4 parameters: id, url, initialSha, finalSha - if (!copyCBORByteToArray(param, ota->params.id, sizeof(ota->params.id))) { - return ArrayParserState::Error; - } - - error = cbor_value_advance(param); - - if ((error != CborNoError) || !copyCBORStringToArray(param, ota->params.url, sizeof(ota->params.url))) { - return ArrayParserState::Error; - } - - error = cbor_value_advance(param); - - if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.initialSha256, sizeof(ota->params.initialSha256))) { - return ArrayParserState::Error; - } - - error = cbor_value_advance(param); - - if ((error != CborNoError) || !copyCBORByteToArray(param, ota->params.finalSha256, sizeof(ota->params.finalSha256))) { - return ArrayParserState::Error; - } - - return ArrayParserState::LeaveArray; -} - -CBORMessageDecoder::ArrayParserState CBORMessageDecoder::handle_Param(CborValue * param, Message * message) { - - switch (message->id) - { - case CommandId::ThingUpdateCmdId: - return CBORMessageDecoder::decodeThingUpdateCmd(param, message); - - case CommandId::ThingDetachCmdId: - return CBORMessageDecoder::decodeThingDetachCmd(param, message); - - case CommandId::TimezoneCommandDownId: - return CBORMessageDecoder::decodeTimezoneCommandDown(param, message); - - case CommandId::LastValuesUpdateCmdId: - return CBORMessageDecoder::decodeLastValuesUpdateCmd(param, message); - - case CommandId::OtaUpdateCmdDownId: - return CBORMessageDecoder::decodeOtaUpdateCmdDown(param, message); - - default: - return ArrayParserState::MessageNotSupported; - } - - return ArrayParserState::LeaveArray; -} diff --git a/src/cbor/MessageDecoder.h b/src/cbor/MessageDecoder.h deleted file mode 100644 index 2ade0eaf7..000000000 --- a/src/cbor/MessageDecoder.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - This file is part of the ArduinoIoTCloud library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#ifndef ARDUINO_CBOR_MESSAGE_DECODER_H_ -#define ARDUINO_CBOR_MESSAGE_DECODER_H_ - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include - -#undef max -#undef min -#include - -#include "CBOR.h" -#include "../interfaces/Decoder.h" -#include - -/****************************************************************************** - CLASS DECLARATION - ******************************************************************************/ - -class CBORMessageDecoder: public Decoder -{ -public: - CBORMessageDecoder() { } - CBORMessageDecoder(CBORMessageDecoder const &) { } - - /* decode a CBOR payload received from the cloud */ - Decoder::Status decode(Message * msg, uint8_t const * const payload, size_t& length); - -private: - - enum class DecoderState { - Success, - MessageNotSupported, - MalformedMessage, - Error - }; - - enum class ArrayParserState { - EnterArray, - ParseParam, - LeaveArray, - Complete, - Error, - MessageNotSupported - }; - - ArrayParserState handle_EnterArray(CborValue * main_iter, CborValue * array_iter); - ArrayParserState handle_Param(CborValue * param, Message * message); - ArrayParserState handle_LeaveArray(CborValue * main_iter, CborValue * array_iter); - - bool ifNumericConvertToDouble(CborValue * value_iter, double * numeric_val); - double convertCborHalfFloatToDouble(uint16_t const half_val); - - // Message specific decoders - ArrayParserState decodeThingUpdateCmd(CborValue * param, Message * message); - ArrayParserState decodeThingDetachCmd(CborValue * param, Message * message); - ArrayParserState decodeTimezoneCommandDown(CborValue * param, Message * message); - ArrayParserState decodeLastValuesUpdateCmd(CborValue * param, Message * message); - ArrayParserState decodeOtaUpdateCmdDown(CborValue * param, Message * message); - -}; - -#endif /* ARDUINO_CBOR_MESSAGE_DECODER_H_ */ From 7e6f473f8d04822563543b2e830c6aa57c1647db Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Tue, 25 Feb 2025 17:11:38 +0100 Subject: [PATCH 12/40] Adapted name change of Message decoder for ArduinoIoTCloud subclasses --- src/ArduinoIoTCloudNotecard.cpp | 8 ++++---- src/ArduinoIoTCloudTCP.cpp | 4 ++-- src/ArduinoIoTCloudTCP.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ArduinoIoTCloudNotecard.cpp b/src/ArduinoIoTCloudNotecard.cpp index e9ec4a742..fac028e61 100644 --- a/src/ArduinoIoTCloudNotecard.cpp +++ b/src/ArduinoIoTCloudNotecard.cpp @@ -25,8 +25,8 @@ #include #include "cbor/CBOREncoder.h" -#include "cbor/MessageDecoder.h" -#include "cbor/MessageEncoder.h" +#include "cbor/IoTCloudMessageDecoder.h" +#include "cbor/IoTCloudMessageEncoder.h" /****************************************************************************** * CONSTANTS @@ -309,7 +309,7 @@ void ArduinoIoTCloudNotecard::processCommand(const uint8_t *buf, size_t len) DEBUG_VERBOSE("ArduinoIoTCloudNotecard::%s [%d] received %d bytes", __FUNCTION__, millis(), len); CBORMessageDecoder decoder; - if (decoder.decode((Message*)&command, buf, len) != Decoder::Status::Error) { + if (decoder.decode((Message*)&command, buf, len) != MessageDecoder::Status::Error) { DEBUG_VERBOSE("ArduinoIoTCloudNotecard::%s [%d] received command id %d", __FUNCTION__, millis(), command.c.id); switch (command.c.id) { @@ -429,7 +429,7 @@ void ArduinoIoTCloudNotecard::sendCommandMsgToCloud(Message * msg_) CBORMessageEncoder encoder; NotecardConnectionHandler *notecard_connection = reinterpret_cast(_connection); - if (encoder.encode(msg_, data, bytes_encoded) == Encoder::Status::Complete) { + if (encoder.encode(msg_, data, bytes_encoded) == MessageEncoder::Status::Complete) { if (CBOR_LORA_PAYLOAD_MAX_SIZE < bytes_encoded) { DEBUG_WARNING("Encoded %d bytes for Command Message. Exceeds maximum payload size of %d bytes, and cannot be sent to cloud.", bytes_encoded, CBOR_LORA_PAYLOAD_MAX_SIZE); } else if (bytes_encoded > 0) { diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index cc6db00ca..07eb70091 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -413,7 +413,7 @@ void ArduinoIoTCloudTCP::handleMessage(int length) CBORMessageDecoder decoder; size_t buffer_length = length; - if (decoder.decode((Message*)&command, bytes, buffer_length) != Decoder::Status::Error) { + if (decoder.decode((Message*)&command, bytes, buffer_length) != MessageDecoder::Status::Error) { DEBUG_VERBOSE("ArduinoIoTCloudTCP::%s [%d] received command id %d", __FUNCTION__, millis(), command.c.id); switch (command.c.id) { @@ -507,7 +507,7 @@ void ArduinoIoTCloudTCP::sendMessage(Message * msg) break; } - if (encoder.encode(msg, data, bytes_encoded) == Encoder::Status::Complete && + if (encoder.encode(msg, data, bytes_encoded) == MessageEncoder::Status::Complete && bytes_encoded > 0) { write(_messageTopicOut, data, bytes_encoded); } else { diff --git a/src/ArduinoIoTCloudTCP.h b/src/ArduinoIoTCloudTCP.h index ebd49f610..6560a5f70 100644 --- a/src/ArduinoIoTCloudTCP.h +++ b/src/ArduinoIoTCloudTCP.h @@ -41,8 +41,8 @@ #include #endif -#include "cbor/MessageDecoder.h" -#include "cbor/MessageEncoder.h" +#include "cbor/IoTCloudMessageDecoder.h" +#include "cbor/IoTCloudMessageEncoder.h" /****************************************************************************** CONSTANTS From ca81751d8e6ecf2e1589b19c5b2229ffa8277bc3 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 30 Jan 2025 15:28:29 +0100 Subject: [PATCH 13/40] Including Arduino_CloudUtils in cmake unit testing --- .github/workflows/unit-tests.yml | 1 - .gitmodules | 0 extras/test/CMakeLists.txt | 56 +++++++--- extras/test/src/test_command_decode.cpp | 81 +++++++------- extras/test/src/test_command_encode.cpp | 134 ++++++++++++------------ 5 files changed, 148 insertions(+), 124 deletions(-) create mode 100644 .gitmodules diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 10d06cf27..b2194c155 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -32,7 +32,6 @@ jobs: coverage-exclude-paths: | - '*/extras/test/*' - '/usr/*' - - '*/src/cbor/lib/*' coverage-data-path: ${{ env.COVERAGE_DATA_PATH }} # A token is used to avoid intermittent spurious job failures caused by rate limiting. diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..e69de29bb diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index 7ab5f1f5c..bee215561 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -14,16 +14,42 @@ FetchContent_Declare( GIT_TAG v3.4.0 ) +FetchContent_Declare( + cloudutils + GIT_REPOSITORY https://github.com/arduino-libraries/Arduino_CloudUtils.git + GIT_TAG main +) + FetchContent_MakeAvailable(Catch2) +FetchContent_MakeAvailable(cloudutils) ########################################################################## include_directories(include) include_directories(../../src) +include_directories(../../src/message) include_directories(../../src/cbor) include_directories(../../src/property) include_directories(../../src/utility/time) +# add_library(cloudutils STATIC IMPORTED GLOBAL) +add_library(cloudutils INTERFACE) + +target_include_directories( + cloudutils INTERFACE + ${cloudutils_SOURCE_DIR}/src/ +) + +target_include_directories( + cloudutils INTERFACE + ${cloudutils_SOURCE_DIR}/src/cbor +) + +target_include_directories( + cloudutils INTERFACE + ${cloudutils_SOURCE_DIR}/src/interfaces +) + ########################################################################## set(CMAKE_CXX_STANDARD 11) @@ -67,21 +93,22 @@ set(TEST_DUT_SRCS ../../src/property/PropertyContainer.cpp ../../src/cbor/CBORDecoder.cpp ../../src/cbor/CBOREncoder.cpp - ../../src/cbor/MessageDecoder.cpp - ../../src/cbor/MessageEncoder.cpp - ../../src/cbor/CBOR.cpp - ../../src/cbor/lib/tinycbor/src/cborencoder.c - ../../src/cbor/lib/tinycbor/src/cborencoder_close_container_checked.c - ../../src/cbor/lib/tinycbor/src/cborerrorstrings.c - ../../src/cbor/lib/tinycbor/src/cborparser.c - ../../src/cbor/lib/tinycbor/src/cborparser_dup_string.c - ../../src/cbor/lib/tinycbor/src/cborpretty.c - ../../src/cbor/lib/tinycbor/src/cborpretty_stdio.c - ../../src/cbor/lib/tinycbor/src/cbortojson.c - ../../src/cbor/lib/tinycbor/src/cborvalidation.c - ../../src/cbor/lib/tinycbor/src/open_memstream.c + ../../src/cbor/IoTCloudMessageDecoder.cpp + ../../src/cbor/IoTCloudMessageEncoder.cpp + + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborencoder.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborencoder_close_container_checked.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborerrorstrings.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborparser.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborparser_dup_string.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborpretty.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborpretty_stdio.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cbortojson.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/cborvalidation.c + ${cloudutils_SOURCE_DIR}/src/cbor/tinycbor/src/open_memstream.c + ${cloudutils_SOURCE_DIR}/src/cbor/MessageDecoder.cpp + ${cloudutils_SOURCE_DIR}/src/cbor/MessageEncoder.cpp ) - ########################################################################## set(TEST_TARGET_SRCS @@ -108,6 +135,7 @@ add_executable( ${TEST_TARGET_SRCS} ) +target_link_libraries( ${TEST_TARGET} cloudutils) target_link_libraries( ${TEST_TARGET} Catch2WithMain ) ########################################################################## diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp index e17ec3b7e..dcb3520e6 100644 --- a/extras/test/src/test_command_decode.cpp +++ b/extras/test/src/test_command_decode.cpp @@ -12,6 +12,7 @@ #include #include +#include #include /****************************************************************************** @@ -39,11 +40,11 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); const char *thingIdToMatch = "e4494d55-872a-4fd2-9646-92f87949394c"; THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Complete); + REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(strcmp(command.thingUpdateCmd.params.thing_id, thingIdToMatch) == 0); REQUIRE(command.c.id == ThingUpdateCmdId); } @@ -68,11 +69,11 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); const char *thingIdToMatch = "e4494d55-872a-4fd2-9646-92f87949394c"; THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Complete); + REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(strcmp(command.thingDetachCmd.params.thing_id, thingIdToMatch) == 0); REQUIRE(command.c.id == ThingDetachCmdId); } @@ -93,10 +94,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -114,10 +115,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -139,10 +140,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Complete); + REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(command.timezoneCommandDown.params.offset == (uint32_t)1708963873); REQUIRE(command.timezoneCommandDown.params.until == (uint32_t)2024579473); REQUIRE(command.c.id == TimezoneCommandDownId); @@ -169,10 +170,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Complete); + REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(command.lastValuesUpdateCmd.params.length == 13); REQUIRE(command.lastValuesUpdateCmd.params.last_values[0] == (uint8_t)0x00); REQUIRE(command.lastValuesUpdateCmd.params.last_values[1] == (uint8_t)0x01); @@ -249,14 +250,14 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); uint8_t otaIdToMatch[ID_SIZE] = { 0xC7, 0x3C, 0xB0, 0x45, 0xF9, 0xC2, 0x43, 0x45, 0x85, 0xAF, 0xFA, 0x36, 0xA3, 0x07, 0xBF, 0xE7}; const char *urlToMatch = "https://boards-int.oniudra.cc/storage/firmware/v1/df1eac9c7bd63473fffb117f9873703e4ec955931e267f26262b0949bc16dc49"; THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Complete); + REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(memcmp(command.otaUpdateCmdDown.params.id, otaIdToMatch, ID_SIZE) == 0); REQUIRE(strcmp(command.otaUpdateCmdDown.params.url, urlToMatch) == 0); // Initial SHA256 check @@ -388,10 +389,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -452,10 +453,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -511,10 +512,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -570,10 +571,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is successful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -596,10 +597,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - OtaBeginUp is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -619,10 +620,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - ThingBeginCmd is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -639,10 +640,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - LastValuesBeginCmd is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -662,10 +663,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - DeviceBeginCmd is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -690,10 +691,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - OtaProgressCmdUp is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -710,10 +711,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful - TimezoneCommandUp is not supported") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -735,10 +736,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -759,10 +760,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } @@ -776,10 +777,10 @@ SCENARIO("Test the decoding of command messages") { size_t payload_length = sizeof(payload) / sizeof(uint8_t); CBORMessageDecoder decoder; - Decoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); THEN("The decode is unsuccessful") { - REQUIRE(err == Decoder::Status::Error); + REQUIRE(err == MessageDecoder::Status::Error); } } diff --git a/extras/test/src/test_command_encode.cpp b/extras/test/src/test_command_encode.cpp index a39c54a54..0ae71d661 100644 --- a/extras/test/src/test_command_encode.cpp +++ b/extras/test/src/test_command_encode.cpp @@ -11,7 +11,9 @@ #include #include +#include #include +#include /****************************************************************************** TEST CODE @@ -32,15 +34,7 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x00, 0x00, 0x81, 0x58, 0x20, - 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010000 # tag(65536) @@ -48,9 +42,16 @@ SCENARIO("Test the encoding of command messages") { // 58 20 # bytes(32) // 01020304 THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x00, 0x00, 0x81, 0x58, 0x20, + 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + })); } } @@ -69,12 +70,7 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x03, 0x00, 0x81, 0x68, 0x74, - 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010300 # tag(66304) @@ -83,9 +79,13 @@ SCENARIO("Test the encoding of command messages") { // 7468696E675F6964 # "thing_id" THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x03, 0x00, 0x81, 0x68, 0x74, + 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64 + })); } } @@ -100,19 +100,18 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x05, 0x00, 0x80 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010500 # tag(66816) // 80 # array(0) THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x05, 0x00, 0x80 + })); } } @@ -130,12 +129,7 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x07, 0x00, 0x81, 0x65, 0x32, - 0x2e, 0x30, 0x2e, 0x30 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010700 # tag(67328) @@ -143,9 +137,13 @@ SCENARIO("Test the encoding of command messages") { // 65 # text(5) // 322E302E30 # "2.0.0" THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x07, 0x00, 0x81, 0x65, 0x32, + 0x2e, 0x30, 0x2e, 0x30 + })); } } @@ -168,14 +166,7 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x02, 0x00, 0x84, 0x50, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xe1, - 0x20, 0x18, 0x64 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010200 # tag(66048) @@ -186,9 +177,15 @@ SCENARIO("Test the encoding of command messages") { // 20 # negative(0) // 18 64 # unsigned(100) THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x02, 0x00, 0x84, 0x50, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xe1, + 0x20, 0x18, 0x64 + })); } } @@ -203,19 +200,18 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); - - uint8_t expected_result[] = { - 0xda, 0x00, 0x01, 0x08, 0x00, 0x80 - }; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); // Test the encoding is // DA 00010800 # tag(67584) // 80 # array(0) THEN("The encoding is successful") { - REQUIRE(err == Encoder::Status::Complete); - REQUIRE(bytes_encoded == sizeof(expected_result)); - REQUIRE(memcmp(buffer, expected_result, sizeof(expected_result)) == 0); + REQUIRE(err == MessageEncoder::Status::Complete); + std::vector res(buffer, buffer+bytes_encoded); + + REQUIRE_THAT(res, Catch::Matchers::Equals(std::vector{ + 0xda, 0x00, 0x01, 0x08, 0x00, 0x80 + })); } } @@ -233,10 +229,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - ThingUpdateCmdId is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } @@ -254,10 +250,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - SetTimezoneCommand is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } @@ -277,10 +273,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - LastValuesUpdateCmd is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } @@ -295,10 +291,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - OtaUpdateCmdDown is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } @@ -313,10 +309,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - ThingDetachCmd is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } @@ -331,10 +327,10 @@ SCENARIO("Test the encoding of command messages") { size_t bytes_encoded = sizeof(buffer); CBORMessageEncoder encoder; - Encoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); THEN("The encoding is unsuccessful - UnknownCmdId is not supported") { - REQUIRE(err == Encoder::Status::Error); + REQUIRE(err == MessageEncoder::Status::Error); } } } From 36bcb9216af28f9bcef1d674bf74bcba5edb95d0 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 27 Jan 2025 14:14:19 +0100 Subject: [PATCH 14/40] Adapting ArduinoIotCloud to Cloud utils new encode/decode --- src/ArduinoIoTCloudDevice.cpp | 2 +- src/ArduinoIoTCloudThing.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudDevice.cpp b/src/ArduinoIoTCloudDevice.cpp index 574ad3a76..58f00d202 100644 --- a/src/ArduinoIoTCloudDevice.cpp +++ b/src/ArduinoIoTCloudDevice.cpp @@ -48,7 +48,7 @@ int ArduinoCloudDevice::connected() { void ArduinoCloudDevice::handleMessage(Message *m) { _command = UnknownCmdId; if (m != nullptr) { - _command = m->id; + _command = static_cast(m->id); } /* Run through the state machine. */ diff --git a/src/ArduinoIoTCloudThing.cpp b/src/ArduinoIoTCloudThing.cpp index 5b07d0a5f..a6bb74190 100644 --- a/src/ArduinoIoTCloudThing.cpp +++ b/src/ArduinoIoTCloudThing.cpp @@ -69,7 +69,7 @@ int ArduinoCloudThing::connected() { void ArduinoCloudThing::handleMessage(Message* m) { _command = UnknownCmdId; if (m != nullptr) { - _command = m->id; + _command = static_cast(m->id); if (_command == TimezoneCommandDownId) { _utcOffset = reinterpret_cast(m)->params.offset; _utcOffsetExpireTime = reinterpret_cast(m)->params.until; From 56afa6b8bc2425719f911a64d2c27a2387390ec1 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Thu, 6 Feb 2025 10:42:06 +0100 Subject: [PATCH 15/40] Including Arduino_CoudUtils in CI for compile examples --- .github/workflows/compile-examples.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index dd4a9c776..b465ffd85 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -26,6 +26,7 @@ jobs: - name: Arduino_DebugUtils - name: ArduinoMqttClient - name: Arduino_SecureElement + - name: Arduino_CloudUtils # sketch paths to compile (recursive) for all boards UNIVERSAL_SKETCH_PATHS: | - examples/ArduinoIoTCloud-Advanced From 6190d7255ac9e886b3c196b3c60a5bdf6ef15969 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 10 Mar 2025 15:31:52 +0100 Subject: [PATCH 16/40] improving test coverage for cbor encode --- extras/test/src/test_command_encode.cpp | 315 ++++++++++++++++++++++++ 1 file changed, 315 insertions(+) diff --git a/extras/test/src/test_command_encode.cpp b/extras/test/src/test_command_encode.cpp index 0ae71d661..3b7ae4425 100644 --- a/extras/test/src/test_command_encode.cpp +++ b/extras/test/src/test_command_encode.cpp @@ -55,6 +55,49 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the OtaBeginUp message, but the buffer is not big enough to accommodate the encode the array open") + { + OtaBeginUp command; + uint8_t sha[SHA256_SIZE] = {0x01, 0x02, 0x03, 0x04}; + memcpy(command.params.sha, sha, SHA256_SIZE); + + command.c.id = CommandId::OtaBeginUpId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010000 # tag(65536) + // 81 # array(1) + // 58 20 # bytes(32) + // 01020304 + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the OtaBeginUp message, but the buffer is not big enough to accommodate the sha") + { + OtaBeginUp command; + uint8_t sha[SHA256_SIZE] = {0x01, 0x02, 0x03, 0x04}; + memcpy(command.params.sha, sha, SHA256_SIZE); + + command.c.id = CommandId::OtaBeginUpId; + + uint8_t buffer[6]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010000 # tag(65536) + // 81 # array(1) + // 58 20 # bytes(32) + // 01020304 + REQUIRE(err == MessageEncoder::Status::Error); + } /****************************************************************************/ @@ -89,6 +132,50 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the ThingBeginCmd message, but the buffer is not big enough to accommodate the array open") + { + ThingBeginCmd command; + String thing_id = "thing_id"; + strcpy(command.params.thing_id, thing_id.c_str()); + + command.c.id = CommandId::ThingBeginCmdId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010300 # tag(66304) + // 81 # array(1) + // 68 # text(8) + // 7468696E675F6964 # "thing_id" + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the ThingBeginCmd message, but the buffer is not big enough to accommodate the thing id") + { + ThingBeginCmd command; + String thing_id = "thing_id"; + strcpy(command.params.thing_id, thing_id.c_str()); + + command.c.id = CommandId::ThingBeginCmdId; + + uint8_t buffer[6]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010300 # tag(66304) + // 81 # array(1) + // 68 # text(8) + // 7468696E675F6964 # "thing_id" + REQUIRE(err == MessageEncoder::Status::Error); + } + /****************************************************************************/ WHEN("Encode the LastValuesBeginCmd message") @@ -115,6 +202,23 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the LastValuesBeginCmd message, but the buffer is not big enough to accommodate the array open") + { + LastValuesBeginCmd command; + command.c.id = CommandId::LastValuesBeginCmdId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010500 # tag(66816) + // 80 # array(0) + REQUIRE(err == MessageEncoder::Status::Error); + } + /**************************************************************************/ WHEN("Encode the DeviceBeginCmd message") @@ -147,6 +251,50 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the DeviceBeginCmd message, but the buffer is not big enough to accommodate the array open") + { + DeviceBeginCmd command; + String lib_version = "2.0.0"; + strcpy(command.params.lib_version, lib_version.c_str()); + + command.c.id = CommandId::DeviceBeginCmdId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010700 # tag(67328) + // 81 # array(1) + // 65 # text(5) + // 322E302E30 # "2.0.0" + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the DeviceBeginCmd message, but the buffer is not big enough to accommodate the lib version") + { + DeviceBeginCmd command; + String lib_version = "2.0.0"; + strcpy(command.params.lib_version, lib_version.c_str()); + + command.c.id = CommandId::DeviceBeginCmdId; + + uint8_t buffer[6]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010700 # tag(67328) + // 81 # array(1) + // 65 # text(5) + // 322E302E30 # "2.0.0" + REQUIRE(err == MessageEncoder::Status::Error); + } + /****************************************************************************/ WHEN("Encode the OtaProgressCmdUp message") @@ -189,6 +337,156 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the OtaProgressCmdUp message, but the buffer is not big enough to accommodate the array open") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the OtaProgressCmdUp message, but the buffer is not big enough to accommodate the id") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[6]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the OtaProgressCmdUp message, but the buffer is not big enough to accommodate the state") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[23]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the OtaProgressCmdUp message, but the buffer is not big enough to accommodate the state_data") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[24]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + REQUIRE(err == MessageEncoder::Status::Error); + } + + WHEN("Encode the OtaProgressCmdUp message, but the buffer is not big enough to accommodate the time") + { + OtaProgressCmdUp command; + command.params.time = 2; + + uint8_t id[ID_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + memcpy(command.params.id, id, ID_SIZE); + command.params.state = 1; + command.params.state_data = -1; + command.params.time = 100; + + command.c.id = CommandId::OtaProgressCmdUpId; + + uint8_t buffer[25]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010200 # tag(66048) + // 84 # array(4) + // 50 # bytes(16) + // 000102030405060708090A0B0C0D0E0F # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f" + // E1 # primitive(1) + // 20 # negative(0) + // 18 64 # unsigned(100) + REQUIRE(err == MessageEncoder::Status::Error); + } + /****************************************************************************/ WHEN("Encode the TimezoneCommandUp message") @@ -215,6 +513,23 @@ SCENARIO("Test the encoding of command messages") { } } + WHEN("Encode the TimezoneCommandUp message, but the buffer is not big enough to accommodate the array open") + { + TimezoneCommandUp command; + command.c.id = CommandId::TimezoneCommandUpId; + + uint8_t buffer[5]; + size_t bytes_encoded = sizeof(buffer); + + CBORMessageEncoder encoder; + MessageEncoder::Status err = encoder.encode((Message*)&command, buffer, bytes_encoded); + + // Test the encoding is + // DA 00010800 # tag(67584) + // 80 # array(0) + REQUIRE(err == MessageEncoder::Status::Error); + } + /****************************************************************************/ WHEN("Encode the ThingUpdateCmdId message") From 85d49dbced79d1ad7a7096b196bbdb341cf6cc6c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 4 Mar 2025 11:44:38 +0100 Subject: [PATCH 17/40] utility: remove TimedAttemp --- extras/test/CMakeLists.txt | 2 - extras/test/src/test_TimedAttempt.cpp | 186 -------------------------- src/ArduinoIoTCloudDevice.h | 2 +- src/ArduinoIoTCloudThing.h | 2 +- src/utility/time/TimedAttempt.cpp | 84 ------------ src/utility/time/TimedAttempt.h | 42 ------ 6 files changed, 2 insertions(+), 316 deletions(-) delete mode 100644 extras/test/src/test_TimedAttempt.cpp delete mode 100644 src/utility/time/TimedAttempt.cpp delete mode 100644 src/utility/time/TimedAttempt.h diff --git a/extras/test/CMakeLists.txt b/extras/test/CMakeLists.txt index bee215561..ae745aeaf 100644 --- a/extras/test/CMakeLists.txt +++ b/extras/test/CMakeLists.txt @@ -79,7 +79,6 @@ set(TEST_SRCS src/test_writeOnly.cpp src/test_writeOnDemand.cpp src/test_writeOnChange.cpp - src/test_TimedAttempt.cpp ) set(TEST_UTIL_SRCS @@ -88,7 +87,6 @@ set(TEST_UTIL_SRCS ) set(TEST_DUT_SRCS - ../../src/utility/time/TimedAttempt.cpp ../../src/property/Property.cpp ../../src/property/PropertyContainer.cpp ../../src/cbor/CBORDecoder.cpp diff --git a/extras/test/src/test_TimedAttempt.cpp b/extras/test/src/test_TimedAttempt.cpp deleted file mode 100644 index 8e07a2ee9..000000000 --- a/extras/test/src/test_TimedAttempt.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - Copyright (c) 2024 Arduino. All rights reserved. -*/ - -/****************************************************************************** - INCLUDE - ******************************************************************************/ - -#include - -#include -#include -#include -#include - -/****************************************************************************** - TEST CODE - ******************************************************************************/ - -SCENARIO("Test broker connection retries") -{ - TimedAttempt _connection_attempt(0,0); - - _connection_attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); - - /* 100000 retries are more or less 37 days without connection */ - while(_connection_attempt.getRetryCount() < 100000) { - _connection_attempt.retry(); - - switch(_connection_attempt.getRetryCount()) { - case 1: - REQUIRE(_connection_attempt.getWaitTime() == 2000); - break; - case 2: - REQUIRE(_connection_attempt.getWaitTime() == 4000); - break; - case 3: - REQUIRE(_connection_attempt.getWaitTime() == 8000); - break; - case 4: - REQUIRE(_connection_attempt.getWaitTime() == 16000); - break; - default: - REQUIRE(_connection_attempt.getWaitTime() == 32000); - break; - } - } -} - -SCENARIO("Test thing id request with no answer from the cloud") -{ - TimedAttempt _attachAttempt(0,0); - - _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); - - /* 100000 retries are more or less 37 days of requests */ - while(_attachAttempt.getRetryCount() < 100000) { - _attachAttempt.retry(); - - switch(_attachAttempt.getRetryCount()) { - case 1: - REQUIRE(_attachAttempt.getWaitTime() == 4000); - break; - case 2: - REQUIRE(_attachAttempt.getWaitTime() == 8000); - break; - case 3: - REQUIRE(_attachAttempt.getWaitTime() == 16000); - break; - default: - REQUIRE(_attachAttempt.getWaitTime() == 32000); - break; - } - } -} - -SCENARIO("Test thing id request of a detached device") -{ - TimedAttempt _attachAttempt(0,0); - - _attachAttempt.begin(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms); - - while(_attachAttempt.getRetryCount() < 100000) { - _attachAttempt.retry(); - - switch(_attachAttempt.getRetryCount()) { - case 1: - REQUIRE(_attachAttempt.getWaitTime() == 4000); - _attachAttempt.reconfigure(AIOT_CONFIG_THING_ID_REQUEST_RETRY_DELAY_ms * - AIOT_CONFIG_DEVICE_REGISTERED_RETRY_DELAY_k, - AIOT_CONFIG_MAX_THING_ID_REQUEST_RETRY_DELAY_ms * - AIOT_CONFIG_MAX_DEVICE_REGISTERED_RETRY_DELAY_k); - break; - case 2: - REQUIRE(_attachAttempt.getWaitTime() == 80000); - break; - case 3: - REQUIRE(_attachAttempt.getWaitTime() == 160000); - break; - case 4: - REQUIRE(_attachAttempt.getWaitTime() == 320000); - break; - case 5: - REQUIRE(_attachAttempt.getWaitTime() == 640000); - break; - default: - REQUIRE(_attachAttempt.getWaitTime() == 1280000); - break; - } - } -} - -SCENARIO("Test last value request") -{ - TimedAttempt _syncAttempt(0,0); - - _syncAttempt.begin(AIOT_CONFIG_TIMEOUT_FOR_LASTVALUES_SYNC_ms); - - /* 100000 retries are more or less 37 days of requests */ - while(_syncAttempt.getRetryCount() < 100000) { - _syncAttempt.retry(); - - switch(_syncAttempt.getRetryCount()) { - default: - REQUIRE(_syncAttempt.getWaitTime() == 30000); - break; - } - } -} - -SCENARIO("Test isExpired() and isRetry()") -{ - TimedAttempt attempt(0,0); - - attempt.begin(AIOT_CONFIG_RECONNECTION_RETRY_DELAY_ms, - AIOT_CONFIG_MAX_RECONNECTION_RETRY_DELAY_ms); - - /* Initial condition */ - set_millis(0); - REQUIRE(attempt.isExpired() == false); - REQUIRE(attempt.isRetry() == false); - - /* Normal retry 2000ms */ - attempt.retry(); - REQUIRE(attempt.isRetry() == true); - set_millis(1000); - REQUIRE(attempt.isExpired() == false); - set_millis(1999); - REQUIRE(attempt.isExpired() == false); - set_millis(2000); - REQUIRE(attempt.isExpired() == false); - set_millis(2001); - REQUIRE(attempt.isExpired() == true); - - /* Retry with rollover 4000ms */ - set_millis(ULONG_MAX - 1999); - attempt.retry(); - REQUIRE(attempt.isRetry() == true); - set_millis(0); - REQUIRE(attempt.isExpired() == false); - set_millis(1999); - REQUIRE(attempt.isExpired() == false); - set_millis(2000); - REQUIRE(attempt.isExpired() == false); - set_millis(2001); - REQUIRE(attempt.isExpired() == true); - - /* Normal retry 8000ms */ - set_millis(4000); - attempt.retry(); - REQUIRE(attempt.isRetry() == true); - set_millis(4000); - REQUIRE(attempt.isExpired() == false); - set_millis(11999); - REQUIRE(attempt.isExpired() == false); - set_millis(12000); - REQUIRE(attempt.isExpired() == false); - set_millis(12001); - REQUIRE(attempt.isExpired() == true); - - attempt.reset(); - REQUIRE(attempt.isRetry() == false); -} diff --git a/src/ArduinoIoTCloudDevice.h b/src/ArduinoIoTCloudDevice.h index 294acfde5..5bfe052fa 100644 --- a/src/ArduinoIoTCloudDevice.h +++ b/src/ArduinoIoTCloudDevice.h @@ -15,8 +15,8 @@ * INCLUDE ******************************************************************************/ +#include #include "interfaces/CloudProcess.h" -#include "utility/time/TimedAttempt.h" #include "property/PropertyContainer.h" /****************************************************************************** diff --git a/src/ArduinoIoTCloudThing.h b/src/ArduinoIoTCloudThing.h index de52bc002..d6a9b8dac 100644 --- a/src/ArduinoIoTCloudThing.h +++ b/src/ArduinoIoTCloudThing.h @@ -16,8 +16,8 @@ * INCLUDE ******************************************************************************/ +#include #include "interfaces/CloudProcess.h" -#include "utility/time/TimedAttempt.h" #include "property/PropertyContainer.h" /****************************************************************************** diff --git a/src/utility/time/TimedAttempt.cpp b/src/utility/time/TimedAttempt.cpp deleted file mode 100644 index 70b6d0253..000000000 --- a/src/utility/time/TimedAttempt.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - This file is part of the Arduino_SecureElement library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -/****************************************************************************** - * INCLUDE - ******************************************************************************/ - -#include -#include "TimedAttempt.h" - -/****************************************************************************** - * CTOR/DTOR - ******************************************************************************/ - -TimedAttempt::TimedAttempt(unsigned long minDelay, unsigned long maxDelay) -: _minDelay(minDelay) -, _maxDelay(maxDelay) { -} - -/****************************************************************************** - * PUBLIC MEMBER FUNCTIONS - ******************************************************************************/ - -void TimedAttempt::begin(unsigned long delay) { - _retryCount = 0; - _retryDelay = 0; - _retryTick = 0; - _minDelay = delay; - _maxDelay = delay; -} - -void TimedAttempt::begin(unsigned long minDelay, unsigned long maxDelay) { - _retryCount = 0; - _retryDelay = 0; - _retryTick = 0; - _minDelay = minDelay; - _maxDelay = maxDelay; -} - -unsigned long TimedAttempt::reconfigure(unsigned long minDelay, unsigned long maxDelay) { - _minDelay = minDelay; - _maxDelay = maxDelay; - return reload(); -} - -unsigned long TimedAttempt::retry() { - _retryCount++; - return reload(); -} - -unsigned long TimedAttempt::reload() { - unsigned long shift = _retryCount > 31 ? 31 : _retryCount; - unsigned long delay = (1UL << shift) * _minDelay; - _retryDelay = min(delay, _maxDelay); - _retryTick = millis(); - return _retryDelay; -} - -void TimedAttempt::reset() { - _retryCount = 0; -} - -bool TimedAttempt::isRetry() { - return _retryCount > 0; -} - -bool TimedAttempt::isExpired() { - return millis() - _retryTick > _retryDelay; -} - -unsigned int TimedAttempt::getRetryCount() { - return _retryCount; -} - -unsigned int TimedAttempt::getWaitTime() { - return _retryDelay; -} diff --git a/src/utility/time/TimedAttempt.h b/src/utility/time/TimedAttempt.h deleted file mode 100644 index 9a95e310f..000000000 --- a/src/utility/time/TimedAttempt.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of the Arduino_SecureElement library. - - Copyright (c) 2024 Arduino SA - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. -*/ - -#ifndef TIMED_ATTEMPT_H -#define TIMED_ATTEMPT_H - -/****************************************************************************** - * CLASS DECLARATION - ******************************************************************************/ - -class TimedAttempt { - -public: - TimedAttempt(unsigned long minDelay, unsigned long maxDelay); - - void begin(unsigned long delay); - void begin(unsigned long minDelay, unsigned long maxDelay); - unsigned long reconfigure(unsigned long minDelay, unsigned long maxDelay); - unsigned long retry(); - unsigned long reload(); - void reset(); - bool isRetry(); - bool isExpired(); - unsigned int getRetryCount(); - unsigned int getWaitTime(); - -private: - unsigned long _minDelay; - unsigned long _maxDelay; - unsigned long _retryTick; - unsigned long _retryDelay; - unsigned int _retryCount; -}; - -#endif /* TIMED_ATTEMPT_H */ From f594fa24c5d1296491ebdd8125bfe1dab76005bc Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 10 Mar 2025 16:24:13 +0100 Subject: [PATCH 18/40] improving decode unit testing by means of REQUIRE_THAT --- extras/test/src/test_command_decode.cpp | 110 +++++++----------------- 1 file changed, 29 insertions(+), 81 deletions(-) diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp index dcb3520e6..c6122088f 100644 --- a/extras/test/src/test_command_decode.cpp +++ b/extras/test/src/test_command_decode.cpp @@ -7,6 +7,8 @@ ******************************************************************************/ #include +#include + #include #include @@ -174,20 +176,15 @@ SCENARIO("Test the decoding of command messages") { THEN("The decode is successful") { REQUIRE(err == MessageDecoder::Status::Complete); - REQUIRE(command.lastValuesUpdateCmd.params.length == 13); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[0] == (uint8_t)0x00); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[1] == (uint8_t)0x01); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[2] == (uint8_t)0x02); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[3] == (uint8_t)0x03); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[4] == (uint8_t)0x04); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[5] == (uint8_t)0x05); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[6] == (uint8_t)0x06); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[7] == (uint8_t)0x07); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[8] == (uint8_t)0x08); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[9] == (uint8_t)0x09); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[10] == (uint8_t)0x10); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[11] == (uint8_t)0x11); - REQUIRE(command.lastValuesUpdateCmd.params.last_values[12] == (uint8_t)0x12); + + std::vector last_values(command.lastValuesUpdateCmd.params.last_values, + command.lastValuesUpdateCmd.params.last_values+13); + + REQUIRE_THAT(last_values, + Catch::Matchers::Equals(std::vector{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, + })); + REQUIRE(command.c.id == LastValuesUpdateCmdId); } free(command.lastValuesUpdateCmd.params.last_values); @@ -260,73 +257,24 @@ SCENARIO("Test the decoding of command messages") { REQUIRE(err == MessageDecoder::Status::Complete); REQUIRE(memcmp(command.otaUpdateCmdDown.params.id, otaIdToMatch, ID_SIZE) == 0); REQUIRE(strcmp(command.otaUpdateCmdDown.params.url, urlToMatch) == 0); - // Initial SHA256 check - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[0] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[1] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[2] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[3] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[4] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[5] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[6] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[7] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[8] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[9] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[10] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[11] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[12] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[13] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[14] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[15] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[16] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[17] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[18] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[19] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[20] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[21] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[22] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[23] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[24] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[25] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[26] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[27] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[28] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[29] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[30] == (uint8_t)0x00); - REQUIRE(command.otaUpdateCmdDown.params.initialSha256[31] == (uint8_t)0x00); - - // Final SHA256 check - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[0] == (uint8_t)0xdf); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[1] == (uint8_t)0x1e); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[2] == (uint8_t)0xac); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[3] == (uint8_t)0x9c); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[4] == (uint8_t)0x7b); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[5] == (uint8_t)0xd6); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[6] == (uint8_t)0x34); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[7] == (uint8_t)0x73); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[8] == (uint8_t)0xff); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[9] == (uint8_t)0xfb); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[10] == (uint8_t)0x11); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[11] == (uint8_t)0x7f); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[12] == (uint8_t)0x98); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[13] == (uint8_t)0x73); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[14] == (uint8_t)0x70); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[15] == (uint8_t)0x3e); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[16] == (uint8_t)0x4e); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[17] == (uint8_t)0xc9); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[18] == (uint8_t)0x55); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[19] == (uint8_t)0x93); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[20] == (uint8_t)0x1e); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[21] == (uint8_t)0x26); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[22] == (uint8_t)0x7f); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[23] == (uint8_t)0x26); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[24] == (uint8_t)0x26); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[25] == (uint8_t)0x2b); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[26] == (uint8_t)0x09); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[27] == (uint8_t)0x49); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[28] == (uint8_t)0xbc); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[29] == (uint8_t)0x16); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[30] == (uint8_t)0xdc); - REQUIRE(command.otaUpdateCmdDown.params.finalSha256[31] == (uint8_t)0x49); + + std::vector initialSha256(command.otaUpdateCmdDown.params.initialSha256, + command.otaUpdateCmdDown.params.initialSha256+32); + + REQUIRE_THAT(initialSha256, + Catch::Matchers::Equals(std::vector{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + })); + + std::vector finalSha256(command.otaUpdateCmdDown.params.finalSha256, + command.otaUpdateCmdDown.params.finalSha256+32); + + REQUIRE_THAT(finalSha256, + Catch::Matchers::Equals(std::vector{ + 0xdf, 0x1e, 0xac, 0x9c, 0x7b, 0xd6, 0x34, 0x73, 0xff, 0xfb, 0x11, 0x7f, 0x98, 0x73, 0x70, 0x3e, + 0x4e, 0xc9, 0x55, 0x93, 0x1e, 0x26, 0x7f, 0x26, 0x26, 0x2b, 0x09, 0x49, 0xbc, 0x16, 0xdc, 0x49 + })); REQUIRE(command.c.id == OtaUpdateCmdDownId); } From caa60cd378610b2eba338b2cd97497d919b45d6d Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 10 Mar 2025 16:24:51 +0100 Subject: [PATCH 19/40] Unit testing adding missing test cases for failing decode --- extras/test/src/test_command_decode.cpp | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/extras/test/src/test_command_decode.cpp b/extras/test/src/test_command_decode.cpp index c6122088f..8d75e6c90 100644 --- a/extras/test/src/test_command_decode.cpp +++ b/extras/test/src/test_command_decode.cpp @@ -152,6 +152,124 @@ SCENARIO("Test the decoding of command messages") { } } + WHEN("Decode the TimezoneCommandDown message, but until is not present") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 81 # array(1) + 1A 65DCB821 # unsigned(1708963873) + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x81, 0x1A, 0x65, + 0xDC, 0xB8, 0x21}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + + WHEN("Decode the TimezoneCommandDown message, but offset is incorrectly encoded") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 81 # array(1) + 1A 65DC # unsigned(26076) + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x81, 0x1A,}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + + WHEN("Decode the TimezoneCommandDown message, but offset is a byte array instead of an integer") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 81 # array(2) + 4D # bytes(13) + 00010203040506070809101112 # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\u0010\u0011\u0012" + 1A 65DCB821 # unsigned(1708963873) + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x81, 0x21, 0x4D, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x10, 0x11, 0x12, 0x1A, 0x65, 0xDC, + 0xB8,}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + + WHEN("Decode the TimezoneCommandDown message, but until is a byte array instead of an integer") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 82 # array(2) + 1A 65DCB821 # unsigned(1708963873) + 4D # bytes(13) + 00010203040506070809101112 # "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\u0010\u0011\u0012" + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x82, 0x1A, 0x65, + 0xDC, 0xB8, 0x21, 0x4D, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, + 0x12}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + + WHEN("Decode the TimezoneCommandDown message, but until is incorrectly encoded") + { + CommandDown command; + + /* + DA 00010764 # tag(67840) + 82 # array(2) + 1A 65DCB821 # unsigned(1708963873) + 1A 78AC # unsigned(30892) + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x09, 0x00, 0x82, 0x1A, 0x65, + 0xDC, 0xB8, 0x21, 0x1A, 0x78, 0xAC}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + /****************************************************************************/ WHEN("Decode the LastValuesUpdateCmd message") @@ -190,6 +308,29 @@ SCENARIO("Test the decoding of command messages") { free(command.lastValuesUpdateCmd.params.last_values); } + WHEN("Decode the LastValuesUpdateCmd message, but lastvalues is an integer") + { + CommandDown command; + + /* + DA 00010600 # tag(67072) + 81 # array(1) + 1A 65DCB821 # unsigned(1708963873) + + */ + + uint8_t const payload[] = {0xDA, 0x00, 0x01, 0x06, 0x00, 0x81, 0x1A, 0x65, + 0xDC, 0xB8, 0x21}; + + size_t payload_length = sizeof(payload) / sizeof(uint8_t); + CBORMessageDecoder decoder; + MessageDecoder::Status err = decoder.decode((Message*)&command, payload, payload_length); + + THEN("The decode is unsuccessful") { + REQUIRE(err == MessageDecoder::Status::Error); + } + } + /****************************************************************************/ WHEN("Decode the OtaUpdateCmdDown message") From 8c8296090b1890a0b5320ff4269d1f213c0e1ef0 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Thu, 3 Apr 2025 15:10:49 +0200 Subject: [PATCH 20/40] TCP: fix nina-fw minimum required version after certificate update --- src/ArduinoIoTCloudTCP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 07eb70091..469bee89f 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -183,8 +183,8 @@ int ArduinoIoTCloudTCP::begin(bool const enable_watchdog, String brokerAddress, #endif // OTA_ENABLED && !defined(OFFLOADED_DOWNLOAD) && defined(OTA_BASIC_AUTH) #ifdef BOARD_HAS_OFFLOADED_ECCX08 - if (String(WiFi.firmwareVersion()) < String("1.4.4")) { - DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.4.4, current %s", __FUNCTION__, WiFi.firmwareVersion()); + if (String(WiFi.firmwareVersion()) < String("1.6.0")) { + DEBUG_ERROR("ArduinoIoTCloudTCP::%s In order to connect to Arduino IoT Cloud, NINA firmware needs to be >= 1.6.0, current %s", __FUNCTION__, WiFi.firmwareVersion()); return 0; } #endif /* BOARD_HAS_OFFLOADED_ECCX08 */ From aa35ba55be6e770e5598a1194f9b716a1e4d7e6f Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 10 Apr 2025 18:39:05 +0200 Subject: [PATCH 21/40] TCP print bearssl error for all boards using bearssl --- src/ArduinoIoTCloudTCP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ArduinoIoTCloudTCP.cpp b/src/ArduinoIoTCloudTCP.cpp index 469bee89f..dc8bb86d0 100644 --- a/src/ArduinoIoTCloudTCP.cpp +++ b/src/ArduinoIoTCloudTCP.cpp @@ -325,7 +325,7 @@ ArduinoIoTCloudTCP::State ArduinoIoTCloudTCP::handle_ConnectMqttBroker() /* Can't connect to the broker. Wait: 2s -> 4s -> 8s -> 16s -> 32s -> 32s ... */ _connection_attempt.retry(); -#if defined (BOARD_STM32H7) && defined(BOARD_HAS_ECCX08) +#if defined(BOARD_HAS_ECCX08) && !defined(BOARD_HAS_OFFLOADED_ECCX08) DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d Mqtt error: %d TLS error: %d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort, _mqttClient.connectError(), _brokerClient.errorCode()); #else DEBUG_ERROR("ArduinoIoTCloudTCP::%s could not connect to %s:%d Error: %d", __FUNCTION__, _brokerAddress.c_str(), _brokerPort, _mqttClient.connectError()); From 5f10263dab90669040b8fc3928f27cf4e21a9b6f Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 12 Aug 2024 09:52:09 +0200 Subject: [PATCH 22/40] Remove local files that will be included from ArduinoBearSSL --- src/tls/BearSSLClient.cpp | 415 -- src/tls/BearSSLClient.h | 120 - src/tls/bearssl/LICENSE.txt | 21 - src/tls/bearssl/aes_big_cbcdec.c | 74 - src/tls/bearssl/aes_big_cbcenc.c | 72 - src/tls/bearssl/aes_big_ctr.c | 89 - src/tls/bearssl/aes_big_ctrcbc.c | 147 - src/tls/bearssl/aes_big_dec.c | 259 -- src/tls/bearssl/aes_big_enc.c | 162 - src/tls/bearssl/aes_common.c | 117 - src/tls/bearssl/aes_ct.c | 333 -- src/tls/bearssl/aes_ct64.c | 403 -- src/tls/bearssl/aes_ct64_cbcdec.c | 109 - src/tls/bearssl/aes_ct64_cbcenc.c | 86 - src/tls/bearssl/aes_ct64_ctr.c | 119 - src/tls/bearssl/aes_ct64_ctrcbc.c | 438 -- src/tls/bearssl/aes_ct64_dec.c | 164 - src/tls/bearssl/aes_ct64_enc.c | 120 - src/tls/bearssl/aes_ct_cbcdec.c | 116 - src/tls/bearssl/aes_ct_cbcenc.c | 96 - src/tls/bearssl/aes_ct_ctr.c | 121 - src/tls/bearssl/aes_ct_ctrcbc.c | 427 -- src/tls/bearssl/aes_ct_dec.c | 175 - src/tls/bearssl/aes_ct_enc.c | 117 - src/tls/bearssl/aes_pwr8.c | 451 -- src/tls/bearssl/aes_pwr8_cbcdec.c | 676 --- src/tls/bearssl/aes_pwr8_cbcenc.c | 422 -- src/tls/bearssl/aes_pwr8_ctr.c | 723 --- src/tls/bearssl/aes_pwr8_ctrcbc.c | 954 ---- src/tls/bearssl/aes_small_cbcdec.c | 74 - src/tls/bearssl/aes_small_cbcenc.c | 72 - src/tls/bearssl/aes_small_ctr.c | 89 - src/tls/bearssl/aes_small_ctrcbc.c | 147 - src/tls/bearssl/aes_small_dec.c | 181 - src/tls/bearssl/aes_small_enc.c | 134 - src/tls/bearssl/aes_x86ni.c | 283 -- src/tls/bearssl/aes_x86ni_cbcdec.c | 228 - src/tls/bearssl/aes_x86ni_cbcenc.c | 133 - src/tls/bearssl/aes_x86ni_ctr.c | 216 - src/tls/bearssl/aesctr_drbg.c | 211 - src/tls/bearssl/asn1enc.c | 98 - src/tls/bearssl/bearssl.h | 170 - src/tls/bearssl/bearssl_aead.h | 1059 ----- src/tls/bearssl/bearssl_block.h | 2618 ----------- src/tls/bearssl/bearssl_ec.h | 883 ---- src/tls/bearssl/bearssl_hash.h | 1346 ------ src/tls/bearssl/bearssl_hmac.h | 241 - src/tls/bearssl/bearssl_kdf.h | 185 - src/tls/bearssl/bearssl_pem.h | 294 -- src/tls/bearssl/bearssl_prf.h | 150 - src/tls/bearssl/bearssl_rand.h | 397 -- src/tls/bearssl/bearssl_rsa.h | 1366 ------ src/tls/bearssl/bearssl_ssl.h | 4301 ------------------ src/tls/bearssl/bearssl_x509.h | 1397 ------ src/tls/bearssl/ccm.c | 351 -- src/tls/bearssl/ccopy.c | 49 - src/tls/bearssl/chacha20_ct.c | 111 - src/tls/bearssl/chacha20_sse2.c | 242 - src/tls/bearssl/config.h | 235 - src/tls/bearssl/dec16be.c | 43 - src/tls/bearssl/dec16le.c | 43 - src/tls/bearssl/dec32be.c | 45 - src/tls/bearssl/dec32le.c | 43 - src/tls/bearssl/dec64be.c | 43 - src/tls/bearssl/dec64le.c | 43 - src/tls/bearssl/des_ct.c | 416 -- src/tls/bearssl/des_ct_cbcdec.c | 92 - src/tls/bearssl/des_ct_cbcenc.c | 74 - src/tls/bearssl/des_support.c | 171 - src/tls/bearssl/des_tab.c | 315 -- src/tls/bearssl/des_tab_cbcdec.c | 90 - src/tls/bearssl/des_tab_cbcenc.c | 72 - src/tls/bearssl/dig_oid.c | 89 - src/tls/bearssl/dig_size.c | 55 - src/tls/bearssl/eax.c | 530 --- src/tls/bearssl/ec_all_m15.c | 126 - src/tls/bearssl/ec_all_m31.c | 126 - src/tls/bearssl/ec_c25519_i15.c | 403 -- src/tls/bearssl/ec_c25519_i31.c | 392 -- src/tls/bearssl/ec_c25519_m15.c | 1483 ------ src/tls/bearssl/ec_c25519_m31.c | 774 ---- src/tls/bearssl/ec_curve25519.c | 51 - src/tls/bearssl/ec_default.c | 41 - src/tls/bearssl/ec_keygen.c | 91 - src/tls/bearssl/ec_p256_m15.c | 2135 --------- src/tls/bearssl/ec_p256_m31.c | 1480 ------ src/tls/bearssl/ec_prime_i15.c | 825 ---- src/tls/bearssl/ec_prime_i31.c | 824 ---- src/tls/bearssl/ec_pubkey.c | 90 - src/tls/bearssl/ec_secp256r1.c | 56 - src/tls/bearssl/ec_secp384r1.c | 62 - src/tls/bearssl/ec_secp521r1.c | 69 - src/tls/bearssl/ecdsa_atr.c | 139 - src/tls/bearssl/ecdsa_default_sign_asn1.c | 41 - src/tls/bearssl/ecdsa_default_sign_raw.c | 41 - src/tls/bearssl/ecdsa_default_vrfy_asn1.c | 41 - src/tls/bearssl/ecdsa_default_vrfy_raw.c | 41 - src/tls/bearssl/ecdsa_i15_bits.c | 52 - src/tls/bearssl/ecdsa_i15_sign_asn1.c | 50 - src/tls/bearssl/ecdsa_i15_sign_raw.c | 179 - src/tls/bearssl/ecdsa_i15_vrfy_asn1.c | 53 - src/tls/bearssl/ecdsa_i15_vrfy_raw.c | 171 - src/tls/bearssl/ecdsa_i31_bits.c | 52 - src/tls/bearssl/ecdsa_i31_sign_asn1.c | 50 - src/tls/bearssl/ecdsa_i31_sign_raw.c | 178 - src/tls/bearssl/ecdsa_i31_vrfy_asn1.c | 53 - src/tls/bearssl/ecdsa_i31_vrfy_raw.c | 170 - src/tls/bearssl/ecdsa_rta.c | 126 - src/tls/bearssl/enc16be.c | 43 - src/tls/bearssl/enc16le.c | 43 - src/tls/bearssl/enc32be.c | 45 - src/tls/bearssl/enc32le.c | 43 - src/tls/bearssl/enc64be.c | 43 - src/tls/bearssl/enc64le.c | 43 - src/tls/bearssl/encode_ec_pk8der.c | 115 - src/tls/bearssl/encode_ec_rawder.c | 166 - src/tls/bearssl/encode_rsa_pk8der.c | 102 - src/tls/bearssl/encode_rsa_rawder.c | 101 - src/tls/bearssl/gcm.c | 323 -- src/tls/bearssl/ghash_ctmul.c | 350 -- src/tls/bearssl/ghash_ctmul32.c | 256 -- src/tls/bearssl/ghash_ctmul64.c | 159 - src/tls/bearssl/ghash_pclmul.c | 394 -- src/tls/bearssl/ghash_pwr8.c | 416 -- src/tls/bearssl/hkdf.c | 112 - src/tls/bearssl/hmac.c | 127 - src/tls/bearssl/hmac_ct.c | 198 - src/tls/bearssl/hmac_drbg.c | 162 - src/tls/bearssl/i15_add.c | 51 - src/tls/bearssl/i15_bitlen.c | 49 - src/tls/bearssl/i15_decmod.c | 129 - src/tls/bearssl/i15_decode.c | 61 - src/tls/bearssl/i15_decred.c | 105 - src/tls/bearssl/i15_encode.c | 61 - src/tls/bearssl/i15_fmont.c | 64 - src/tls/bearssl/i15_iszero.c | 44 - src/tls/bearssl/i15_moddiv.c | 470 -- src/tls/bearssl/i15_modpow.c | 55 - src/tls/bearssl/i15_modpow2.c | 165 - src/tls/bearssl/i15_montmul.c | 189 - src/tls/bearssl/i15_mulacc.c | 66 - src/tls/bearssl/i15_muladd.c | 178 - src/tls/bearssl/i15_ninv15.c | 43 - src/tls/bearssl/i15_reduce.c | 71 - src/tls/bearssl/i15_rshift.c | 52 - src/tls/bearssl/i15_sub.c | 51 - src/tls/bearssl/i15_tmont.c | 41 - src/tls/bearssl/i31_add.c | 51 - src/tls/bearssl/i31_bitlen.c | 49 - src/tls/bearssl/i31_decmod.c | 129 - src/tls/bearssl/i31_decode.c | 62 - src/tls/bearssl/i31_decred.c | 108 - src/tls/bearssl/i31_encode.c | 84 - src/tls/bearssl/i31_fmont.c | 65 - src/tls/bearssl/i31_iszero.c | 44 - src/tls/bearssl/i31_moddiv.c | 493 -- src/tls/bearssl/i31_modpow.c | 70 - src/tls/bearssl/i31_modpow2.c | 165 - src/tls/bearssl/i31_montmul.c | 98 - src/tls/bearssl/i31_mulacc.c | 66 - src/tls/bearssl/i31_muladd.c | 162 - src/tls/bearssl/i31_ninv31.c | 44 - src/tls/bearssl/i31_reduce.c | 71 - src/tls/bearssl/i31_rshift.c | 52 - src/tls/bearssl/i31_sub.c | 51 - src/tls/bearssl/i31_tmont.c | 41 - src/tls/bearssl/i32_add.c | 56 - src/tls/bearssl/i32_bitlen.c | 49 - src/tls/bearssl/i32_decmod.c | 82 - src/tls/bearssl/i32_decode.c | 68 - src/tls/bearssl/i32_decred.c | 112 - src/tls/bearssl/i32_div32.c | 61 - src/tls/bearssl/i32_encode.c | 77 - src/tls/bearssl/i32_fmont.c | 65 - src/tls/bearssl/i32_iszero.c | 44 - src/tls/bearssl/i32_modpow.c | 70 - src/tls/bearssl/i32_montmul.c | 74 - src/tls/bearssl/i32_mulacc.c | 57 - src/tls/bearssl/i32_muladd.c | 143 - src/tls/bearssl/i32_ninv32.c | 44 - src/tls/bearssl/i32_reduce.c | 71 - src/tls/bearssl/i32_sub.c | 56 - src/tls/bearssl/i32_tmont.c | 41 - src/tls/bearssl/i62_modpow2.c | 498 -- src/tls/bearssl/inner.h | 2532 ----------- src/tls/bearssl/md5.c | 213 - src/tls/bearssl/md5sha1.c | 146 - src/tls/bearssl/mgf1.c | 61 - src/tls/bearssl/multihash.c | 171 - src/tls/bearssl/pemdec.c | 531 --- src/tls/bearssl/pemenc.c | 178 - src/tls/bearssl/poly1305_ctmul.c | 265 -- src/tls/bearssl/poly1305_ctmul32.c | 302 -- src/tls/bearssl/poly1305_ctmulq.c | 480 -- src/tls/bearssl/poly1305_i15.c | 226 - src/tls/bearssl/prf.c | 78 - src/tls/bearssl/prf_md5sha1.c | 48 - src/tls/bearssl/prf_sha256.c | 41 - src/tls/bearssl/prf_sha384.c | 41 - src/tls/bearssl/rsa_default_keygen.c | 43 - src/tls/bearssl/rsa_default_modulus.c | 41 - src/tls/bearssl/rsa_default_oaep_decrypt.c | 43 - src/tls/bearssl/rsa_default_oaep_encrypt.c | 43 - src/tls/bearssl/rsa_default_pkcs1_sign.c | 43 - src/tls/bearssl/rsa_default_pkcs1_vrfy.c | 43 - src/tls/bearssl/rsa_default_priv.c | 43 - src/tls/bearssl/rsa_default_privexp.c | 41 - src/tls/bearssl/rsa_default_pub.c | 43 - src/tls/bearssl/rsa_default_pubexp.c | 41 - src/tls/bearssl/rsa_i15_keygen.c | 588 --- src/tls/bearssl/rsa_i15_modulus.c | 104 - src/tls/bearssl/rsa_i15_oaep_decrypt.c | 46 - src/tls/bearssl/rsa_i15_oaep_encrypt.c | 49 - src/tls/bearssl/rsa_i15_pkcs1_sign.c | 42 - src/tls/bearssl/rsa_i15_pkcs1_vrfy.c | 48 - src/tls/bearssl/rsa_i15_priv.c | 214 - src/tls/bearssl/rsa_i15_privexp.c | 325 -- src/tls/bearssl/rsa_i15_pub.c | 118 - src/tls/bearssl/rsa_i15_pubexp.c | 157 - src/tls/bearssl/rsa_i31_keygen.c | 42 - src/tls/bearssl/rsa_i31_keygen_inner.c | 613 --- src/tls/bearssl/rsa_i31_modulus.c | 104 - src/tls/bearssl/rsa_i31_oaep_decrypt.c | 46 - src/tls/bearssl/rsa_i31_oaep_encrypt.c | 49 - src/tls/bearssl/rsa_i31_pkcs1_sign.c | 42 - src/tls/bearssl/rsa_i31_pkcs1_vrfy.c | 48 - src/tls/bearssl/rsa_i31_priv.c | 208 - src/tls/bearssl/rsa_i31_privexp.c | 323 -- src/tls/bearssl/rsa_i31_pub.c | 111 - src/tls/bearssl/rsa_i31_pubexp.c | 157 - src/tls/bearssl/rsa_i32_oaep_decrypt.c | 46 - src/tls/bearssl/rsa_i32_oaep_encrypt.c | 49 - src/tls/bearssl/rsa_i32_pkcs1_sign.c | 42 - src/tls/bearssl/rsa_i32_pkcs1_vrfy.c | 48 - src/tls/bearssl/rsa_i32_priv.c | 165 - src/tls/bearssl/rsa_i32_pub.c | 82 - src/tls/bearssl/rsa_i62_keygen.c | 62 - src/tls/bearssl/rsa_i62_oaep_decrypt.c | 66 - src/tls/bearssl/rsa_i62_oaep_encrypt.c | 69 - src/tls/bearssl/rsa_i62_pkcs1_sign.c | 62 - src/tls/bearssl/rsa_i62_pkcs1_vrfy.c | 68 - src/tls/bearssl/rsa_i62_priv.c | 228 - src/tls/bearssl/rsa_i62_pub.c | 130 - src/tls/bearssl/rsa_oaep_pad.c | 117 - src/tls/bearssl/rsa_oaep_unpad.c | 150 - src/tls/bearssl/rsa_pkcs1_sig_pad.c | 105 - src/tls/bearssl/rsa_pkcs1_sig_unpad.c | 126 - src/tls/bearssl/rsa_ssl_decrypt.c | 57 - src/tls/bearssl/settings.c | 311 -- src/tls/bearssl/sha1.c | 196 - src/tls/bearssl/sha2big.c | 290 -- src/tls/bearssl/sha2small.c | 348 -- src/tls/bearssl/skey_decoder.c | 655 --- src/tls/bearssl/ssl_ccert_single_ec.c | 161 - src/tls/bearssl/ssl_ccert_single_rsa.c | 154 - src/tls/bearssl/ssl_client.c | 83 - src/tls/bearssl/ssl_client_default_rsapub.c | 37 - src/tls/bearssl/ssl_client_full.c | 184 - src/tls/bearssl/ssl_engine.c | 1574 ------- src/tls/bearssl/ssl_engine_default_aescbc.c | 69 - src/tls/bearssl/ssl_engine_default_aesccm.c | 72 - src/tls/bearssl/ssl_engine_default_aesgcm.c | 94 - src/tls/bearssl/ssl_engine_default_chapol.c | 70 - src/tls/bearssl/ssl_engine_default_descbc.c | 42 - src/tls/bearssl/ssl_engine_default_ec.c | 41 - src/tls/bearssl/ssl_engine_default_ecdsa.c | 43 - src/tls/bearssl/ssl_engine_default_rsavrfy.c | 37 - src/tls/bearssl/ssl_hashes.c | 51 - src/tls/bearssl/ssl_hs_client.c | 1920 -------- src/tls/bearssl/ssl_hs_server.c | 2014 -------- src/tls/bearssl/ssl_io.c | 325 -- src/tls/bearssl/ssl_keyexport.c | 88 - src/tls/bearssl/ssl_lru.c | 542 --- src/tls/bearssl/ssl_rec_cbc.c | 445 -- src/tls/bearssl/ssl_rec_ccm.c | 218 - src/tls/bearssl/ssl_rec_chapol.c | 182 - src/tls/bearssl/ssl_rec_gcm.c | 240 - src/tls/bearssl/ssl_scert_single_ec.c | 147 - src/tls/bearssl/ssl_scert_single_rsa.c | 167 - src/tls/bearssl/ssl_server.c | 57 - src/tls/bearssl/ssl_server_full_ec.c | 154 - src/tls/bearssl/ssl_server_full_rsa.c | 137 - src/tls/bearssl/ssl_server_mine2c.c | 76 - src/tls/bearssl/ssl_server_mine2g.c | 76 - src/tls/bearssl/ssl_server_minf2c.c | 76 - src/tls/bearssl/ssl_server_minf2g.c | 76 - src/tls/bearssl/ssl_server_minr2g.c | 75 - src/tls/bearssl/ssl_server_minu2g.c | 75 - src/tls/bearssl/ssl_server_minv2g.c | 75 - src/tls/bearssl/sysrng.c | 174 - src/tls/bearssl/x509_decoder.c | 778 ---- src/tls/bearssl/x509_knownkey.c | 110 - src/tls/bearssl/x509_minimal.c | 1718 ------- src/tls/bearssl/x509_minimal_full.c | 64 - src/tls/utility/eccX08_asn1.h | 46 - src/tls/utility/eccX08_sign_asn1.cpp | 58 - src/tls/utility/eccX08_vrfy_asn1.cpp | 67 - 297 files changed, 71710 deletions(-) delete mode 100644 src/tls/BearSSLClient.cpp delete mode 100644 src/tls/BearSSLClient.h delete mode 100644 src/tls/bearssl/LICENSE.txt delete mode 100644 src/tls/bearssl/aes_big_cbcdec.c delete mode 100644 src/tls/bearssl/aes_big_cbcenc.c delete mode 100644 src/tls/bearssl/aes_big_ctr.c delete mode 100644 src/tls/bearssl/aes_big_ctrcbc.c delete mode 100644 src/tls/bearssl/aes_big_dec.c delete mode 100644 src/tls/bearssl/aes_big_enc.c delete mode 100644 src/tls/bearssl/aes_common.c delete mode 100644 src/tls/bearssl/aes_ct.c delete mode 100644 src/tls/bearssl/aes_ct64.c delete mode 100644 src/tls/bearssl/aes_ct64_cbcdec.c delete mode 100644 src/tls/bearssl/aes_ct64_cbcenc.c delete mode 100644 src/tls/bearssl/aes_ct64_ctr.c delete mode 100644 src/tls/bearssl/aes_ct64_ctrcbc.c delete mode 100644 src/tls/bearssl/aes_ct64_dec.c delete mode 100644 src/tls/bearssl/aes_ct64_enc.c delete mode 100644 src/tls/bearssl/aes_ct_cbcdec.c delete mode 100644 src/tls/bearssl/aes_ct_cbcenc.c delete mode 100644 src/tls/bearssl/aes_ct_ctr.c delete mode 100644 src/tls/bearssl/aes_ct_ctrcbc.c delete mode 100644 src/tls/bearssl/aes_ct_dec.c delete mode 100644 src/tls/bearssl/aes_ct_enc.c delete mode 100644 src/tls/bearssl/aes_pwr8.c delete mode 100644 src/tls/bearssl/aes_pwr8_cbcdec.c delete mode 100644 src/tls/bearssl/aes_pwr8_cbcenc.c delete mode 100644 src/tls/bearssl/aes_pwr8_ctr.c delete mode 100644 src/tls/bearssl/aes_pwr8_ctrcbc.c delete mode 100644 src/tls/bearssl/aes_small_cbcdec.c delete mode 100644 src/tls/bearssl/aes_small_cbcenc.c delete mode 100644 src/tls/bearssl/aes_small_ctr.c delete mode 100644 src/tls/bearssl/aes_small_ctrcbc.c delete mode 100644 src/tls/bearssl/aes_small_dec.c delete mode 100644 src/tls/bearssl/aes_small_enc.c delete mode 100644 src/tls/bearssl/aes_x86ni.c delete mode 100644 src/tls/bearssl/aes_x86ni_cbcdec.c delete mode 100644 src/tls/bearssl/aes_x86ni_cbcenc.c delete mode 100644 src/tls/bearssl/aes_x86ni_ctr.c delete mode 100644 src/tls/bearssl/aesctr_drbg.c delete mode 100644 src/tls/bearssl/asn1enc.c delete mode 100644 src/tls/bearssl/bearssl.h delete mode 100644 src/tls/bearssl/bearssl_aead.h delete mode 100644 src/tls/bearssl/bearssl_block.h delete mode 100644 src/tls/bearssl/bearssl_ec.h delete mode 100644 src/tls/bearssl/bearssl_hash.h delete mode 100644 src/tls/bearssl/bearssl_hmac.h delete mode 100644 src/tls/bearssl/bearssl_kdf.h delete mode 100644 src/tls/bearssl/bearssl_pem.h delete mode 100644 src/tls/bearssl/bearssl_prf.h delete mode 100644 src/tls/bearssl/bearssl_rand.h delete mode 100644 src/tls/bearssl/bearssl_rsa.h delete mode 100644 src/tls/bearssl/bearssl_ssl.h delete mode 100644 src/tls/bearssl/bearssl_x509.h delete mode 100644 src/tls/bearssl/ccm.c delete mode 100644 src/tls/bearssl/ccopy.c delete mode 100644 src/tls/bearssl/chacha20_ct.c delete mode 100644 src/tls/bearssl/chacha20_sse2.c delete mode 100644 src/tls/bearssl/config.h delete mode 100644 src/tls/bearssl/dec16be.c delete mode 100644 src/tls/bearssl/dec16le.c delete mode 100644 src/tls/bearssl/dec32be.c delete mode 100644 src/tls/bearssl/dec32le.c delete mode 100644 src/tls/bearssl/dec64be.c delete mode 100644 src/tls/bearssl/dec64le.c delete mode 100644 src/tls/bearssl/des_ct.c delete mode 100644 src/tls/bearssl/des_ct_cbcdec.c delete mode 100644 src/tls/bearssl/des_ct_cbcenc.c delete mode 100644 src/tls/bearssl/des_support.c delete mode 100644 src/tls/bearssl/des_tab.c delete mode 100644 src/tls/bearssl/des_tab_cbcdec.c delete mode 100644 src/tls/bearssl/des_tab_cbcenc.c delete mode 100644 src/tls/bearssl/dig_oid.c delete mode 100644 src/tls/bearssl/dig_size.c delete mode 100644 src/tls/bearssl/eax.c delete mode 100644 src/tls/bearssl/ec_all_m15.c delete mode 100644 src/tls/bearssl/ec_all_m31.c delete mode 100644 src/tls/bearssl/ec_c25519_i15.c delete mode 100644 src/tls/bearssl/ec_c25519_i31.c delete mode 100644 src/tls/bearssl/ec_c25519_m15.c delete mode 100644 src/tls/bearssl/ec_c25519_m31.c delete mode 100644 src/tls/bearssl/ec_curve25519.c delete mode 100644 src/tls/bearssl/ec_default.c delete mode 100644 src/tls/bearssl/ec_keygen.c delete mode 100644 src/tls/bearssl/ec_p256_m15.c delete mode 100644 src/tls/bearssl/ec_p256_m31.c delete mode 100644 src/tls/bearssl/ec_prime_i15.c delete mode 100644 src/tls/bearssl/ec_prime_i31.c delete mode 100644 src/tls/bearssl/ec_pubkey.c delete mode 100644 src/tls/bearssl/ec_secp256r1.c delete mode 100644 src/tls/bearssl/ec_secp384r1.c delete mode 100644 src/tls/bearssl/ec_secp521r1.c delete mode 100644 src/tls/bearssl/ecdsa_atr.c delete mode 100644 src/tls/bearssl/ecdsa_default_sign_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_default_sign_raw.c delete mode 100644 src/tls/bearssl/ecdsa_default_vrfy_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_default_vrfy_raw.c delete mode 100644 src/tls/bearssl/ecdsa_i15_bits.c delete mode 100644 src/tls/bearssl/ecdsa_i15_sign_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_i15_sign_raw.c delete mode 100644 src/tls/bearssl/ecdsa_i15_vrfy_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_i15_vrfy_raw.c delete mode 100644 src/tls/bearssl/ecdsa_i31_bits.c delete mode 100644 src/tls/bearssl/ecdsa_i31_sign_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_i31_sign_raw.c delete mode 100644 src/tls/bearssl/ecdsa_i31_vrfy_asn1.c delete mode 100644 src/tls/bearssl/ecdsa_i31_vrfy_raw.c delete mode 100644 src/tls/bearssl/ecdsa_rta.c delete mode 100644 src/tls/bearssl/enc16be.c delete mode 100644 src/tls/bearssl/enc16le.c delete mode 100644 src/tls/bearssl/enc32be.c delete mode 100644 src/tls/bearssl/enc32le.c delete mode 100644 src/tls/bearssl/enc64be.c delete mode 100644 src/tls/bearssl/enc64le.c delete mode 100644 src/tls/bearssl/encode_ec_pk8der.c delete mode 100644 src/tls/bearssl/encode_ec_rawder.c delete mode 100644 src/tls/bearssl/encode_rsa_pk8der.c delete mode 100644 src/tls/bearssl/encode_rsa_rawder.c delete mode 100644 src/tls/bearssl/gcm.c delete mode 100644 src/tls/bearssl/ghash_ctmul.c delete mode 100644 src/tls/bearssl/ghash_ctmul32.c delete mode 100644 src/tls/bearssl/ghash_ctmul64.c delete mode 100644 src/tls/bearssl/ghash_pclmul.c delete mode 100644 src/tls/bearssl/ghash_pwr8.c delete mode 100644 src/tls/bearssl/hkdf.c delete mode 100644 src/tls/bearssl/hmac.c delete mode 100644 src/tls/bearssl/hmac_ct.c delete mode 100644 src/tls/bearssl/hmac_drbg.c delete mode 100644 src/tls/bearssl/i15_add.c delete mode 100644 src/tls/bearssl/i15_bitlen.c delete mode 100644 src/tls/bearssl/i15_decmod.c delete mode 100644 src/tls/bearssl/i15_decode.c delete mode 100644 src/tls/bearssl/i15_decred.c delete mode 100644 src/tls/bearssl/i15_encode.c delete mode 100644 src/tls/bearssl/i15_fmont.c delete mode 100644 src/tls/bearssl/i15_iszero.c delete mode 100644 src/tls/bearssl/i15_moddiv.c delete mode 100644 src/tls/bearssl/i15_modpow.c delete mode 100644 src/tls/bearssl/i15_modpow2.c delete mode 100644 src/tls/bearssl/i15_montmul.c delete mode 100644 src/tls/bearssl/i15_mulacc.c delete mode 100644 src/tls/bearssl/i15_muladd.c delete mode 100644 src/tls/bearssl/i15_ninv15.c delete mode 100644 src/tls/bearssl/i15_reduce.c delete mode 100644 src/tls/bearssl/i15_rshift.c delete mode 100644 src/tls/bearssl/i15_sub.c delete mode 100644 src/tls/bearssl/i15_tmont.c delete mode 100644 src/tls/bearssl/i31_add.c delete mode 100644 src/tls/bearssl/i31_bitlen.c delete mode 100644 src/tls/bearssl/i31_decmod.c delete mode 100644 src/tls/bearssl/i31_decode.c delete mode 100644 src/tls/bearssl/i31_decred.c delete mode 100644 src/tls/bearssl/i31_encode.c delete mode 100644 src/tls/bearssl/i31_fmont.c delete mode 100644 src/tls/bearssl/i31_iszero.c delete mode 100644 src/tls/bearssl/i31_moddiv.c delete mode 100644 src/tls/bearssl/i31_modpow.c delete mode 100644 src/tls/bearssl/i31_modpow2.c delete mode 100644 src/tls/bearssl/i31_montmul.c delete mode 100644 src/tls/bearssl/i31_mulacc.c delete mode 100644 src/tls/bearssl/i31_muladd.c delete mode 100644 src/tls/bearssl/i31_ninv31.c delete mode 100644 src/tls/bearssl/i31_reduce.c delete mode 100644 src/tls/bearssl/i31_rshift.c delete mode 100644 src/tls/bearssl/i31_sub.c delete mode 100644 src/tls/bearssl/i31_tmont.c delete mode 100644 src/tls/bearssl/i32_add.c delete mode 100644 src/tls/bearssl/i32_bitlen.c delete mode 100644 src/tls/bearssl/i32_decmod.c delete mode 100644 src/tls/bearssl/i32_decode.c delete mode 100644 src/tls/bearssl/i32_decred.c delete mode 100644 src/tls/bearssl/i32_div32.c delete mode 100644 src/tls/bearssl/i32_encode.c delete mode 100644 src/tls/bearssl/i32_fmont.c delete mode 100644 src/tls/bearssl/i32_iszero.c delete mode 100644 src/tls/bearssl/i32_modpow.c delete mode 100644 src/tls/bearssl/i32_montmul.c delete mode 100644 src/tls/bearssl/i32_mulacc.c delete mode 100644 src/tls/bearssl/i32_muladd.c delete mode 100644 src/tls/bearssl/i32_ninv32.c delete mode 100644 src/tls/bearssl/i32_reduce.c delete mode 100644 src/tls/bearssl/i32_sub.c delete mode 100644 src/tls/bearssl/i32_tmont.c delete mode 100644 src/tls/bearssl/i62_modpow2.c delete mode 100644 src/tls/bearssl/inner.h delete mode 100644 src/tls/bearssl/md5.c delete mode 100644 src/tls/bearssl/md5sha1.c delete mode 100644 src/tls/bearssl/mgf1.c delete mode 100644 src/tls/bearssl/multihash.c delete mode 100644 src/tls/bearssl/pemdec.c delete mode 100644 src/tls/bearssl/pemenc.c delete mode 100644 src/tls/bearssl/poly1305_ctmul.c delete mode 100644 src/tls/bearssl/poly1305_ctmul32.c delete mode 100644 src/tls/bearssl/poly1305_ctmulq.c delete mode 100644 src/tls/bearssl/poly1305_i15.c delete mode 100644 src/tls/bearssl/prf.c delete mode 100644 src/tls/bearssl/prf_md5sha1.c delete mode 100644 src/tls/bearssl/prf_sha256.c delete mode 100644 src/tls/bearssl/prf_sha384.c delete mode 100644 src/tls/bearssl/rsa_default_keygen.c delete mode 100644 src/tls/bearssl/rsa_default_modulus.c delete mode 100644 src/tls/bearssl/rsa_default_oaep_decrypt.c delete mode 100644 src/tls/bearssl/rsa_default_oaep_encrypt.c delete mode 100644 src/tls/bearssl/rsa_default_pkcs1_sign.c delete mode 100644 src/tls/bearssl/rsa_default_pkcs1_vrfy.c delete mode 100644 src/tls/bearssl/rsa_default_priv.c delete mode 100644 src/tls/bearssl/rsa_default_privexp.c delete mode 100644 src/tls/bearssl/rsa_default_pub.c delete mode 100644 src/tls/bearssl/rsa_default_pubexp.c delete mode 100644 src/tls/bearssl/rsa_i15_keygen.c delete mode 100644 src/tls/bearssl/rsa_i15_modulus.c delete mode 100644 src/tls/bearssl/rsa_i15_oaep_decrypt.c delete mode 100644 src/tls/bearssl/rsa_i15_oaep_encrypt.c delete mode 100644 src/tls/bearssl/rsa_i15_pkcs1_sign.c delete mode 100644 src/tls/bearssl/rsa_i15_pkcs1_vrfy.c delete mode 100644 src/tls/bearssl/rsa_i15_priv.c delete mode 100644 src/tls/bearssl/rsa_i15_privexp.c delete mode 100644 src/tls/bearssl/rsa_i15_pub.c delete mode 100644 src/tls/bearssl/rsa_i15_pubexp.c delete mode 100644 src/tls/bearssl/rsa_i31_keygen.c delete mode 100644 src/tls/bearssl/rsa_i31_keygen_inner.c delete mode 100644 src/tls/bearssl/rsa_i31_modulus.c delete mode 100644 src/tls/bearssl/rsa_i31_oaep_decrypt.c delete mode 100644 src/tls/bearssl/rsa_i31_oaep_encrypt.c delete mode 100644 src/tls/bearssl/rsa_i31_pkcs1_sign.c delete mode 100644 src/tls/bearssl/rsa_i31_pkcs1_vrfy.c delete mode 100644 src/tls/bearssl/rsa_i31_priv.c delete mode 100644 src/tls/bearssl/rsa_i31_privexp.c delete mode 100644 src/tls/bearssl/rsa_i31_pub.c delete mode 100644 src/tls/bearssl/rsa_i31_pubexp.c delete mode 100644 src/tls/bearssl/rsa_i32_oaep_decrypt.c delete mode 100644 src/tls/bearssl/rsa_i32_oaep_encrypt.c delete mode 100644 src/tls/bearssl/rsa_i32_pkcs1_sign.c delete mode 100644 src/tls/bearssl/rsa_i32_pkcs1_vrfy.c delete mode 100644 src/tls/bearssl/rsa_i32_priv.c delete mode 100644 src/tls/bearssl/rsa_i32_pub.c delete mode 100644 src/tls/bearssl/rsa_i62_keygen.c delete mode 100644 src/tls/bearssl/rsa_i62_oaep_decrypt.c delete mode 100644 src/tls/bearssl/rsa_i62_oaep_encrypt.c delete mode 100644 src/tls/bearssl/rsa_i62_pkcs1_sign.c delete mode 100644 src/tls/bearssl/rsa_i62_pkcs1_vrfy.c delete mode 100644 src/tls/bearssl/rsa_i62_priv.c delete mode 100644 src/tls/bearssl/rsa_i62_pub.c delete mode 100644 src/tls/bearssl/rsa_oaep_pad.c delete mode 100644 src/tls/bearssl/rsa_oaep_unpad.c delete mode 100644 src/tls/bearssl/rsa_pkcs1_sig_pad.c delete mode 100644 src/tls/bearssl/rsa_pkcs1_sig_unpad.c delete mode 100644 src/tls/bearssl/rsa_ssl_decrypt.c delete mode 100644 src/tls/bearssl/settings.c delete mode 100644 src/tls/bearssl/sha1.c delete mode 100644 src/tls/bearssl/sha2big.c delete mode 100644 src/tls/bearssl/sha2small.c delete mode 100644 src/tls/bearssl/skey_decoder.c delete mode 100644 src/tls/bearssl/ssl_ccert_single_ec.c delete mode 100644 src/tls/bearssl/ssl_ccert_single_rsa.c delete mode 100644 src/tls/bearssl/ssl_client.c delete mode 100644 src/tls/bearssl/ssl_client_default_rsapub.c delete mode 100644 src/tls/bearssl/ssl_client_full.c delete mode 100644 src/tls/bearssl/ssl_engine.c delete mode 100644 src/tls/bearssl/ssl_engine_default_aescbc.c delete mode 100644 src/tls/bearssl/ssl_engine_default_aesccm.c delete mode 100644 src/tls/bearssl/ssl_engine_default_aesgcm.c delete mode 100644 src/tls/bearssl/ssl_engine_default_chapol.c delete mode 100644 src/tls/bearssl/ssl_engine_default_descbc.c delete mode 100644 src/tls/bearssl/ssl_engine_default_ec.c delete mode 100644 src/tls/bearssl/ssl_engine_default_ecdsa.c delete mode 100644 src/tls/bearssl/ssl_engine_default_rsavrfy.c delete mode 100644 src/tls/bearssl/ssl_hashes.c delete mode 100644 src/tls/bearssl/ssl_hs_client.c delete mode 100644 src/tls/bearssl/ssl_hs_server.c delete mode 100644 src/tls/bearssl/ssl_io.c delete mode 100644 src/tls/bearssl/ssl_keyexport.c delete mode 100644 src/tls/bearssl/ssl_lru.c delete mode 100644 src/tls/bearssl/ssl_rec_cbc.c delete mode 100644 src/tls/bearssl/ssl_rec_ccm.c delete mode 100644 src/tls/bearssl/ssl_rec_chapol.c delete mode 100644 src/tls/bearssl/ssl_rec_gcm.c delete mode 100644 src/tls/bearssl/ssl_scert_single_ec.c delete mode 100644 src/tls/bearssl/ssl_scert_single_rsa.c delete mode 100644 src/tls/bearssl/ssl_server.c delete mode 100644 src/tls/bearssl/ssl_server_full_ec.c delete mode 100644 src/tls/bearssl/ssl_server_full_rsa.c delete mode 100644 src/tls/bearssl/ssl_server_mine2c.c delete mode 100644 src/tls/bearssl/ssl_server_mine2g.c delete mode 100644 src/tls/bearssl/ssl_server_minf2c.c delete mode 100644 src/tls/bearssl/ssl_server_minf2g.c delete mode 100644 src/tls/bearssl/ssl_server_minr2g.c delete mode 100644 src/tls/bearssl/ssl_server_minu2g.c delete mode 100644 src/tls/bearssl/ssl_server_minv2g.c delete mode 100644 src/tls/bearssl/sysrng.c delete mode 100644 src/tls/bearssl/x509_decoder.c delete mode 100644 src/tls/bearssl/x509_knownkey.c delete mode 100644 src/tls/bearssl/x509_minimal.c delete mode 100644 src/tls/bearssl/x509_minimal_full.c delete mode 100644 src/tls/utility/eccX08_asn1.h delete mode 100644 src/tls/utility/eccX08_sign_asn1.cpp delete mode 100644 src/tls/utility/eccX08_vrfy_asn1.cpp diff --git a/src/tls/BearSSLClient.cpp b/src/tls/BearSSLClient.cpp deleted file mode 100644 index 995718e93..000000000 --- a/src/tls/BearSSLClient.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (c) 2018 Arduino SA. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include - -#include - -#include "BearSSLTrustAnchors.h" -#include "utility/eccX08_asn1.h" - -#include "BearSSLClient.h" - -extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); - -BearSSLClient::BearSSLClient() : - _noSNI(false), - _get_time_func(nullptr), - _sslio_closing(false) -{ - _ecKey.curve = 0; - _ecKey.x = NULL; - _ecKey.xlen = 0; - - _ecCert.data = NULL; - _ecCert.data_len = 0; - _ecCertDynamic = false; -} - -BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, int myNumTAs, GetTimeCallbackFunc func) : - _client(client), - _TAs(myTAs), - _numTAs(myNumTAs), - _noSNI(false), - _get_time_func(func), - _br_ssl_client_init_function(aiotc_client_profile_init) -{ - assert(_get_time_func != nullptr); - - _ecKey.curve = 0; - _ecKey.x = NULL; - _ecKey.xlen = 0; - - _ecCert.data = NULL; - _ecCert.data_len = 0; - _ecCertDynamic = false; -} - -BearSSLClient::~BearSSLClient() -{ - if (_ecCertDynamic && _ecCert.data) { - free(_ecCert.data); - _ecCert.data = NULL; - } -} - -int BearSSLClient::connect(IPAddress ip, uint16_t port) -{ - if (!_client->connect(ip, port)) { - return 0; - } - - return connectSSL(NULL); -} - -int BearSSLClient::connect(const char* host, uint16_t port) -{ - if (!_client->connect(host, port)) { - return 0; - } - - return connectSSL(_noSNI ? NULL : host); -} - -size_t BearSSLClient::write(uint8_t b) -{ - return write(&b, sizeof(b)); -} - -size_t BearSSLClient::write(const uint8_t *buf, size_t size) -{ - size_t written = 0; - - while (written < size) { - int result = br_sslio_write(&_ioc, buf, size - written); - - if (result < 0) { - break; - } - - buf += result; - written += result; - } - - if (written == size && br_sslio_flush(&_ioc) < 0) { - return 0; - } - - return written; -} - -int BearSSLClient::available() -{ - int available = br_sslio_read_available(&_ioc); - - if (available < 0) { - available = 0; - } - - return available; -} - -int BearSSLClient::read() -{ - byte b; - - if (read(&b, sizeof(b)) == sizeof(b)) { - return b; - } - - return -1; -} - -int BearSSLClient::read(uint8_t *buf, size_t size) -{ - return br_sslio_read(&_ioc, buf, size); -} - -int BearSSLClient::peek() -{ - byte b; - - if (br_sslio_peek(&_ioc, &b, sizeof(b)) == sizeof(b)) { - return b; - } - - return -1; -} - -void BearSSLClient::flush() -{ - br_sslio_flush(&_ioc); - - _client->flush(); -} - -void BearSSLClient::stop() -{ - if (_client->connected()) { - if ((br_ssl_engine_current_state(&_sc.eng) & BR_SSL_CLOSED) == 0) { - _sslio_closing = true; - br_sslio_close(&_ioc); - } - - _client->stop(); - } -} - -uint8_t BearSSLClient::connected() -{ - if (!_client->connected()) { - return 0; - } - - unsigned state = br_ssl_engine_current_state(&_sc.eng); - - if (state == BR_SSL_CLOSED) { - return 0; - } - - return 1; -} - -BearSSLClient::operator bool() -{ - return (*_client); -} - -void BearSSLClient::setInsecure(SNI insecure) -{ - switch (insecure) { - case SNI::Insecure : _noSNI = true; break; - default: _noSNI = false; - } -} - -void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLength) -{ - // HACK: put the key slot info. in the br_ec_private_key structure - _ecKey.curve = 23; - _ecKey.x = (unsigned char*)ecc508KeySlot; - _ecKey.xlen = 32; - - _ecCert.data = (unsigned char*)cert; - _ecCert.data_len = certLength; - _ecCertDynamic = false; -} - -void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[]) -{ - // try to decode the cert - br_pem_decoder_context pemDecoder; - - size_t certLen = strlen(cert); - - // free old data - if (_ecCertDynamic && _ecCert.data) { - free(_ecCert.data); - _ecCert.data = NULL; - } - - // assume the decoded cert is 3/4 the length of the input - _ecCert.data = (unsigned char*)malloc(((certLen * 3) + 3) / 4); - _ecCert.data_len = 0; - - br_pem_decoder_init(&pemDecoder); - - while (certLen) { - size_t len = br_pem_decoder_push(&pemDecoder, cert, certLen); - - cert += len; - certLen -= len; - - switch (br_pem_decoder_event(&pemDecoder)) { - case BR_PEM_BEGIN_OBJ: - br_pem_decoder_setdest(&pemDecoder, BearSSLClient::clientAppendCert, this); - break; - - case BR_PEM_END_OBJ: - if (_ecCert.data_len) { - // done - setEccSlot(ecc508KeySlot, _ecCert.data, _ecCert.data_len); - _ecCertDynamic = true; - return; - } - break; - - case BR_PEM_ERROR: - // failure - free(_ecCert.data); - setEccSlot(ecc508KeySlot, NULL, 0); - return; - } - } -} - -int BearSSLClient::errorCode() -{ - return br_ssl_engine_last_error(&_sc.eng); -} - -int BearSSLClient::connectSSL(const char* host) -{ - /* Ensure this flag is cleared so we don't terminate a just starting connection. */ - _sslio_closing = false; - - // initialize client context with enabled algorithms and trust anchors - _br_ssl_client_init_function(&_sc, &_xc, _TAs, _numTAs); - - br_ssl_engine_set_buffers_bidi(&_sc.eng, _ibuf, sizeof(_ibuf), _obuf, sizeof(_obuf)); - - // inject entropy in engine - unsigned char entropy[32]; - - if (ECCX08.begin() && ECCX08.locked() && ECCX08.random(entropy, sizeof(entropy))) { - // ECC508 random success, add custom ECDSA vfry and EC sign - br_ssl_engine_set_ecdsa(&_sc.eng, eccX08_vrfy_asn1); - br_x509_minimal_set_ecdsa(&_xc, br_ssl_engine_get_ec(&_sc.eng), br_ssl_engine_get_ecdsa(&_sc.eng)); - - // enable client auth using the ECCX08 - if (_ecCert.data_len && _ecKey.xlen) { - br_ssl_client_set_single_ec(&_sc, &_ecCert, 1, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), eccX08_sign_asn1); - } - } else { - // no ECCX08 or random failed, fallback to pseudo random - for (size_t i = 0; i < sizeof(entropy); i++) { - entropy[i] = random(0, 255); - } - } - br_ssl_engine_inject_entropy(&_sc.eng, entropy, sizeof(entropy)); - - // set the hostname used for SNI - br_ssl_client_reset(&_sc, host, 0); - - // get the current time and set it for X.509 validation - uint32_t now = _get_time_func(); - uint32_t days = now / 86400 + 719528; - uint32_t sec = now % 86400; - - br_x509_minimal_set_time(&_xc, days, sec); - - // use our own socket I/O operations - br_sslio_init(&_ioc, &_sc.eng, BearSSLClient::clientRead, this, BearSSLClient::clientWrite, this); - - br_sslio_flush(&_ioc); - - while (1) { - unsigned state = br_ssl_engine_current_state(&_sc.eng); - - if (state & BR_SSL_SENDAPP) { - break; - } else if (state & BR_SSL_CLOSED) { - return 0; - } - } - - return 1; -} - -// #define DEBUGSERIAL Serial - -int BearSSLClient::clientRead(void *ctx, unsigned char *buf, size_t len) -{ - BearSSLClient* bc = (BearSSLClient*)ctx; - Client* c = bc->_client; - - if(bc->_sslio_closing) { - return -1; - } - - if (!c->connected()) { - return -1; - } - - int result = c->read(buf, len); - if (result == -1) { - return 0; - } - -#ifdef DEBUGSERIAL - DEBUGSERIAL.print("BearSSLClient::clientRead - "); - DEBUGSERIAL.print(result); - DEBUGSERIAL.print(" - "); - for (size_t i = 0; i < result; i++) { - byte b = buf[i]; - - if (b < 16) { - DEBUGSERIAL.print("0"); - } - DEBUGSERIAL.print(b, HEX); - } - DEBUGSERIAL.println(); -#endif - - return result; -} - -int BearSSLClient::clientWrite(void *ctx, const unsigned char *buf, size_t len) -{ - BearSSLClient* bc = (BearSSLClient*)ctx; - Client* c = bc->_client; - - if(bc->_sslio_closing) { - return -1; - } - -#ifdef DEBUGSERIAL - DEBUGSERIAL.print("BearSSLClient::clientWrite - "); - DEBUGSERIAL.print(len); - DEBUGSERIAL.print(" - "); - for (size_t i = 0; i < len; i++) { - byte b = buf[i]; - - if (b < 16) { - DEBUGSERIAL.print("0"); - } - DEBUGSERIAL.print(b, HEX); - } - DEBUGSERIAL.println(); -#endif - - if (!c->connected()) { - return -1; - } - - int result = c->write(buf, len); - if (result == 0) { - return -1; - } - - return result; -} - -void BearSSLClient::clientAppendCert(void *ctx, const void *data, size_t len) -{ - BearSSLClient* c = (BearSSLClient*)ctx; - - memcpy(&c->_ecCert.data[c->_ecCert.data_len], data, len); - c->_ecCert.data_len += len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/BearSSLClient.h b/src/tls/BearSSLClient.h deleted file mode 100644 index 32fb18727..000000000 --- a/src/tls/BearSSLClient.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2018 Arduino SA. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _BEAR_SSL_CLIENT_H_ -#define _BEAR_SSL_CLIENT_H_ - -#include -#ifdef BOARD_HAS_ECCX08 - -#ifndef BEAR_SSL_CLIENT_OBUF_SIZE -#define BEAR_SSL_CLIENT_OBUF_SIZE 512 + 85 -#endif - -#ifndef BEAR_SSL_CLIENT_IBUF_SIZE -#define BEAR_SSL_CLIENT_IBUF_SIZE 8192 + 85 + 325 - BEAR_SSL_CLIENT_OBUF_SIZE -#endif - -#include -#include - -#include "bearssl/bearssl.h" - -typedef unsigned long(*GetTimeCallbackFunc)(); - -class BearSSLClient : public Client { - -public: - - BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, int myNumTAs, GetTimeCallbackFunc func); - BearSSLClient(); - virtual ~BearSSLClient(); - - - inline void setClient(Client& client) { _client = &client; } - inline void setProfile(void(*client_init_function)(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trustrust_anchorst_anchors_num)) { _br_ssl_client_init_function = client_init_function; } - inline void setTrustAnchors(const br_x509_trust_anchor* myTAs, int myNumTAs) { _TAs = myTAs; _numTAs = myNumTAs; } - inline void onGetTime(GetTimeCallbackFunc callback) { _get_time_func = callback;} - - virtual int connect(IPAddress ip, uint16_t port); - virtual int connect(const char* host, uint16_t port); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int available(); - virtual int read(); - virtual int read(uint8_t *buf, size_t size); - virtual int peek(); - virtual void flush(); - virtual void stop(); - virtual uint8_t connected(); - virtual operator bool(); - - using Print::write; - - enum class SNI { - Insecure - }; - - void setInsecure(SNI insecure) __attribute__((deprecated("INSECURE. DO NOT USE IN PRODUCTION"))); - - void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength); - void setEccSlot(int ecc508KeySlot, const char cert[]); - - int errorCode(); - -private: - int connectSSL(const char* host); - static int clientRead(void *ctx, unsigned char *buf, size_t len); - static int clientWrite(void *ctx, const unsigned char *buf, size_t len); - static void clientAppendCert(void *ctx, const void *data, size_t len); - -private: - Client* _client; - const br_x509_trust_anchor* _TAs; - int _numTAs; - bool _noSNI; - GetTimeCallbackFunc _get_time_func; - - br_ec_private_key _ecKey; - br_x509_certificate _ecCert; - bool _ecCertDynamic; - - /* FIXME By introducing _sslio_closing we are overriding the correct behaviour of SSL protocol - * where the client is require to correctly close the ssl session. In the way we use it - * we are blocking bearssl from sending any data on the underlying level, this fix requires - * further investigation in the bearssl code - */ - bool _sslio_closing; - br_ssl_client_context _sc; - br_x509_minimal_context _xc; - unsigned char _ibuf[BEAR_SSL_CLIENT_IBUF_SIZE]; - unsigned char _obuf[BEAR_SSL_CLIENT_OBUF_SIZE]; - br_sslio_context _ioc; - - void (*_br_ssl_client_init_function)(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ - -#endif diff --git a/src/tls/bearssl/LICENSE.txt b/src/tls/bearssl/LICENSE.txt deleted file mode 100644 index 088502032..000000000 --- a/src/tls/bearssl/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2016 Thomas Pornin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/tls/bearssl/aes_big_cbcdec.c b/src/tls/bearssl/aes_big_cbcdec.c deleted file mode 100644 index ff7b693f8..000000000 --- a/src/tls/bearssl/aes_big_cbcdec.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_big_cbcdec_vtable; - ctx->num_rounds = br_aes_big_keysched_inv(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - unsigned char tmp[16]; - int i; - - memcpy(tmp, buf, 16); - br_aes_big_decrypt(ctx->num_rounds, ctx->skey, buf); - for (i = 0; i < 16; i ++) { - buf[i] ^= ivbuf[i]; - } - memcpy(ivbuf, tmp, 16); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_big_cbcdec_vtable = { - sizeof(br_aes_big_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_big_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_big_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_big_cbcenc.c b/src/tls/bearssl/aes_big_cbcenc.c deleted file mode 100644 index 6bdbac199..000000000 --- a/src/tls/bearssl/aes_big_cbcenc.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_big_cbcenc_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - int i; - - for (i = 0; i < 16; i ++) { - buf[i] ^= ivbuf[i]; - } - br_aes_big_encrypt(ctx->num_rounds, ctx->skey, buf); - memcpy(ivbuf, buf, 16); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_big_cbcenc_vtable = { - sizeof(br_aes_big_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_big_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_big_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_big_ctr.c b/src/tls/bearssl/aes_big_ctr.c deleted file mode 100644 index 965edc056..000000000 --- a/src/tls/bearssl/aes_big_ctr.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_big_ctr_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -uint32_t -br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - - buf = data; - while (len > 0) { - unsigned char tmp[16]; - - memcpy(tmp, iv, 12); - br_enc32be(tmp + 12, cc ++); - br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); - if (len <= 16) { - xorbuf(buf, tmp, len); - break; - } - xorbuf(buf, tmp, 16); - buf += 16; - len -= 16; - } - return cc; -} - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_big_ctr_vtable = { - sizeof(br_aes_big_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_big_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_big_ctr_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_big_ctrcbc.c b/src/tls/bearssl/aes_big_ctrcbc.c deleted file mode 100644 index 28343e4a1..000000000 --- a/src/tls/bearssl/aes_big_ctrcbc.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_big_ctrcbc_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -void -br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len) -{ - unsigned char *buf, *bctr; - uint32_t cc0, cc1, cc2, cc3; - - buf = data; - bctr = ctr; - cc3 = br_dec32be(bctr + 0); - cc2 = br_dec32be(bctr + 4); - cc1 = br_dec32be(bctr + 8); - cc0 = br_dec32be(bctr + 12); - while (len > 0) { - unsigned char tmp[16]; - uint32_t carry; - - br_enc32be(tmp + 0, cc3); - br_enc32be(tmp + 4, cc2); - br_enc32be(tmp + 8, cc1); - br_enc32be(tmp + 12, cc0); - br_aes_big_encrypt(ctx->num_rounds, ctx->skey, tmp); - xorbuf(buf, tmp, 16); - buf += 16; - len -= 16; - cc0 ++; - carry = (~(cc0 | -cc0)) >> 31; - cc1 += carry; - carry &= (~(cc1 | -cc1)) >> 31; - cc2 += carry; - carry &= (~(cc2 | -cc2)) >> 31; - cc3 += carry; - } - br_enc32be(bctr + 0, cc3); - br_enc32be(bctr + 4, cc2); - br_enc32be(bctr + 8, cc1); - br_enc32be(bctr + 12, cc0); -} - -/* see bearssl_block.h */ -void -br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len) -{ - const unsigned char *buf; - - buf = data; - while (len > 0) { - xorbuf(cbcmac, buf, 16); - br_aes_big_encrypt(ctx->num_rounds, ctx->skey, cbcmac); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -void -br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - br_aes_big_ctrcbc_ctr(ctx, ctr, data, len); - br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len); -} - -/* see bearssl_block.h */ -void -br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - br_aes_big_ctrcbc_mac(ctx, cbcmac, data, len); - br_aes_big_ctrcbc_ctr(ctx, ctr, data, len); -} - -/* see bearssl_block.h */ -const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable = { - sizeof(br_aes_big_ctrcbc_keys), - 16, - 4, - (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) - &br_aes_big_ctrcbc_init, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_big_ctrcbc_encrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_big_ctrcbc_decrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, size_t)) - &br_aes_big_ctrcbc_ctr, - (void (*)(const br_block_ctrcbc_class *const *, - void *, const void *, size_t)) - &br_aes_big_ctrcbc_mac -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_big_dec.c b/src/tls/bearssl/aes_big_dec.c deleted file mode 100644 index 3d407670b..000000000 --- a/src/tls/bearssl/aes_big_dec.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Inverse S-box (used in key schedule for decryption). - */ -static const unsigned char iS[] = { - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, - 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, - 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, - 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, - 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, - 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, - 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, - 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, - 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, - 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, - 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, - 0x55, 0x21, 0x0C, 0x7D -}; - -static const uint32_t iSsm0[] = { - 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, 0x1F9D45F1, - 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, - 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, 0xDEB15A49, 0x25BA1B67, - 0x45EA0E98, 0x5DFEC0E1, 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6, - 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, - 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, - 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, 0x63DF4A18, 0xE51A3182, - 0x97513360, 0x62537F45, 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94, - 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, - 0xE31F8F57, 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, - 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, 0xA779B492, - 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A, - 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, - 0x5E719F06, 0xBD6E1051, 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, - 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997, - 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB, - 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, 0x09808683, 0x322BED48, - 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, - 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F, - 0xB4EE96D2, 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16, - 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, 0xF28BC7AD, - 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, - 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, 0x8B432976, 0xCB23C6DC, - 0xB6EDFC68, 0xB8E4F163, 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120, - 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, - 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, - 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, 0x87494EC7, 0xD938D1C1, - 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4, - 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, - 0x2E39F75E, 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, - 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, 0x6E5918F4, - 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6, - 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, - 0xC6A59430, 0x35A266C0, 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, - 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D, - 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F, - 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, 0xB3671D5A, 0x92DBD252, - 0xE9105633, 0x6DD64713, 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, - 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F, - 0x1814CE79, 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86, - 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, 0xBCE2250C, - 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, - 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742 -}; - -static unsigned -mul2(unsigned x) -{ - x <<= 1; - return x ^ ((unsigned)(-(int)(x >> 8)) & 0x11B); -} - -static unsigned -mul9(unsigned x) -{ - return x ^ mul2(mul2(mul2(x))); -} - -static unsigned -mulb(unsigned x) -{ - unsigned x2; - - x2 = mul2(x); - return x ^ x2 ^ mul2(mul2(x2)); -} - -static unsigned -muld(unsigned x) -{ - unsigned x4; - - x4 = mul2(mul2(x)); - return x ^ x4 ^ mul2(x4); -} - -static unsigned -mule(unsigned x) -{ - unsigned x2, x4; - - x2 = mul2(x); - x4 = mul2(x2); - return x2 ^ x4 ^ mul2(x4); -} - -/* see inner.h */ -unsigned -br_aes_big_keysched_inv(uint32_t *skey, const void *key, size_t key_len) -{ - unsigned num_rounds; - int i, m; - - /* - * Sub-keys for decryption are distinct from encryption sub-keys - * in that InvMixColumns() is already applied for the inner - * rounds. - */ - num_rounds = br_aes_keysched(skey, key, key_len); - m = (int)(num_rounds << 2); - for (i = 4; i < m; i ++) { - uint32_t p; - unsigned p0, p1, p2, p3; - uint32_t q0, q1, q2, q3; - - p = skey[i]; - p0 = p >> 24; - p1 = (p >> 16) & 0xFF; - p2 = (p >> 8) & 0xFF; - p3 = p & 0xFF; - q0 = mule(p0) ^ mulb(p1) ^ muld(p2) ^ mul9(p3); - q1 = mul9(p0) ^ mule(p1) ^ mulb(p2) ^ muld(p3); - q2 = muld(p0) ^ mul9(p1) ^ mule(p2) ^ mulb(p3); - q3 = mulb(p0) ^ muld(p1) ^ mul9(p2) ^ mule(p3); - skey[i] = (q0 << 24) | (q1 << 16) | (q2 << 8) | q3; - } - return num_rounds; -} - -static inline uint32_t -rotr(uint32_t x, int n) -{ - return (x << (32 - n)) | (x >> n); -} - -#define iSboxExt0(x) (iSsm0[x]) -#define iSboxExt1(x) (rotr(iSsm0[x], 8)) -#define iSboxExt2(x) (rotr(iSsm0[x], 16)) -#define iSboxExt3(x) (rotr(iSsm0[x], 24)) - -/* see bearssl.h */ -void -br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data) -{ - unsigned char *buf; - uint32_t s0, s1, s2, s3; - uint32_t t0, t1, t2, t3; - unsigned u; - - buf = data; - s0 = br_dec32be(buf); - s1 = br_dec32be(buf + 4); - s2 = br_dec32be(buf + 8); - s3 = br_dec32be(buf + 12); - s0 ^= skey[(num_rounds << 2) + 0]; - s1 ^= skey[(num_rounds << 2) + 1]; - s2 ^= skey[(num_rounds << 2) + 2]; - s3 ^= skey[(num_rounds << 2) + 3]; - for (u = num_rounds - 1; u > 0; u --) { - uint32_t v0 = iSboxExt0(s0 >> 24) - ^ iSboxExt1((s3 >> 16) & 0xFF) - ^ iSboxExt2((s2 >> 8) & 0xFF) - ^ iSboxExt3(s1 & 0xFF); - uint32_t v1 = iSboxExt0(s1 >> 24) - ^ iSboxExt1((s0 >> 16) & 0xFF) - ^ iSboxExt2((s3 >> 8) & 0xFF) - ^ iSboxExt3(s2 & 0xFF); - uint32_t v2 = iSboxExt0(s2 >> 24) - ^ iSboxExt1((s1 >> 16) & 0xFF) - ^ iSboxExt2((s0 >> 8) & 0xFF) - ^ iSboxExt3(s3 & 0xFF); - uint32_t v3 = iSboxExt0(s3 >> 24) - ^ iSboxExt1((s2 >> 16) & 0xFF) - ^ iSboxExt2((s1 >> 8) & 0xFF) - ^ iSboxExt3(s0 & 0xFF); - s0 = v0; - s1 = v1; - s2 = v2; - s3 = v3; - s0 ^= skey[u << 2]; - s1 ^= skey[(u << 2) + 1]; - s2 ^= skey[(u << 2) + 2]; - s3 ^= skey[(u << 2) + 3]; - } - t0 = ((uint32_t)iS[s0 >> 24] << 24) - | ((uint32_t)iS[(s3 >> 16) & 0xFF] << 16) - | ((uint32_t)iS[(s2 >> 8) & 0xFF] << 8) - | (uint32_t)iS[s1 & 0xFF]; - t1 = ((uint32_t)iS[s1 >> 24] << 24) - | ((uint32_t)iS[(s0 >> 16) & 0xFF] << 16) - | ((uint32_t)iS[(s3 >> 8) & 0xFF] << 8) - | (uint32_t)iS[s2 & 0xFF]; - t2 = ((uint32_t)iS[s2 >> 24] << 24) - | ((uint32_t)iS[(s1 >> 16) & 0xFF] << 16) - | ((uint32_t)iS[(s0 >> 8) & 0xFF] << 8) - | (uint32_t)iS[s3 & 0xFF]; - t3 = ((uint32_t)iS[s3 >> 24] << 24) - | ((uint32_t)iS[(s2 >> 16) & 0xFF] << 16) - | ((uint32_t)iS[(s1 >> 8) & 0xFF] << 8) - | (uint32_t)iS[s0 & 0xFF]; - s0 = t0 ^ skey[0]; - s1 = t1 ^ skey[1]; - s2 = t2 ^ skey[2]; - s3 = t3 ^ skey[3]; - br_enc32be(buf, s0); - br_enc32be(buf + 4, s1); - br_enc32be(buf + 8, s2); - br_enc32be(buf + 12, s3); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_big_enc.c b/src/tls/bearssl/aes_big_enc.c deleted file mode 100644 index 1d5a690a2..000000000 --- a/src/tls/bearssl/aes_big_enc.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define S br_aes_S - -static const uint32_t Ssm0[] = { - 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, - 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, - 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D, - 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, - 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, - 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, - 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4, - 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, - 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, - 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, - 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E, - 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, - 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, - 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, - 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, - 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, - 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, - 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, - 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, - 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, - 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, - 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, - 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2, - 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, - 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, - 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, - 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256, - 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, - 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, - 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, - 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA, - 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, - 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, - 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, - 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, - 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, - 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, - 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, - 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, - 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, - 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, - 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, - 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A -}; - -static inline uint32_t -rotr(uint32_t x, int n) -{ - return (x << (32 - n)) | (x >> n); -} - -#define SboxExt0(x) (Ssm0[x]) -#define SboxExt1(x) (rotr(Ssm0[x], 8)) -#define SboxExt2(x) (rotr(Ssm0[x], 16)) -#define SboxExt3(x) (rotr(Ssm0[x], 24)) - - -/* see bearssl.h */ -void -br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data) -{ - unsigned char *buf; - uint32_t s0, s1, s2, s3; - uint32_t t0, t1, t2, t3; - unsigned u; - - buf = data; - s0 = br_dec32be(buf); - s1 = br_dec32be(buf + 4); - s2 = br_dec32be(buf + 8); - s3 = br_dec32be(buf + 12); - s0 ^= skey[0]; - s1 ^= skey[1]; - s2 ^= skey[2]; - s3 ^= skey[3]; - for (u = 1; u < num_rounds; u ++) { - uint32_t v0, v1, v2, v3; - - v0 = SboxExt0(s0 >> 24) - ^ SboxExt1((s1 >> 16) & 0xFF) - ^ SboxExt2((s2 >> 8) & 0xFF) - ^ SboxExt3(s3 & 0xFF); - v1 = SboxExt0(s1 >> 24) - ^ SboxExt1((s2 >> 16) & 0xFF) - ^ SboxExt2((s3 >> 8) & 0xFF) - ^ SboxExt3(s0 & 0xFF); - v2 = SboxExt0(s2 >> 24) - ^ SboxExt1((s3 >> 16) & 0xFF) - ^ SboxExt2((s0 >> 8) & 0xFF) - ^ SboxExt3(s1 & 0xFF); - v3 = SboxExt0(s3 >> 24) - ^ SboxExt1((s0 >> 16) & 0xFF) - ^ SboxExt2((s1 >> 8) & 0xFF) - ^ SboxExt3(s2 & 0xFF); - s0 = v0; - s1 = v1; - s2 = v2; - s3 = v3; - s0 ^= skey[u << 2]; - s1 ^= skey[(u << 2) + 1]; - s2 ^= skey[(u << 2) + 2]; - s3 ^= skey[(u << 2) + 3]; - } - t0 = ((uint32_t)S[s0 >> 24] << 24) - | ((uint32_t)S[(s1 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s2 >> 8) & 0xFF] << 8) - | (uint32_t)S[s3 & 0xFF]; - t1 = ((uint32_t)S[s1 >> 24] << 24) - | ((uint32_t)S[(s2 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s3 >> 8) & 0xFF] << 8) - | (uint32_t)S[s0 & 0xFF]; - t2 = ((uint32_t)S[s2 >> 24] << 24) - | ((uint32_t)S[(s3 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s0 >> 8) & 0xFF] << 8) - | (uint32_t)S[s1 & 0xFF]; - t3 = ((uint32_t)S[s3 >> 24] << 24) - | ((uint32_t)S[(s0 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s1 >> 8) & 0xFF] << 8) - | (uint32_t)S[s2 & 0xFF]; - s0 = t0 ^ skey[num_rounds << 2]; - s1 = t1 ^ skey[(num_rounds << 2) + 1]; - s2 = t2 ^ skey[(num_rounds << 2) + 2]; - s3 = t3 ^ skey[(num_rounds << 2) + 3]; - br_enc32be(buf, s0); - br_enc32be(buf + 4, s1); - br_enc32be(buf + 8, s2); - br_enc32be(buf + 12, s3); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_common.c b/src/tls/bearssl/aes_common.c deleted file mode 100644 index 485bb1a22..000000000 --- a/src/tls/bearssl/aes_common.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const uint32_t Rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, - 0x40000000, 0x80000000, 0x1B000000, 0x36000000 -}; - -#define S br_aes_S - -/* see inner.h */ -const unsigned char br_aes_S[] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, - 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, - 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, - 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, - 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, - 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, - 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, - 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, - 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, - 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, - 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, - 0xB0, 0x54, 0xBB, 0x16 -}; - -static uint32_t -SubWord(uint32_t x) -{ - return ((uint32_t)S[x >> 24] << 24) - | ((uint32_t)S[(x >> 16) & 0xFF] << 16) - | ((uint32_t)S[(x >> 8) & 0xFF] << 8) - | (uint32_t)S[x & 0xFF]; -} - -/* see inner.h */ -unsigned -br_aes_keysched(uint32_t *skey, const void *key, size_t key_len) -{ - unsigned num_rounds; - int i, j, k, nk, nkf; - - switch (key_len) { - case 16: - num_rounds = 10; - break; - case 24: - num_rounds = 12; - break; - case 32: - num_rounds = 14; - break; - default: - /* abort(); */ - return 0; - } - nk = (int)(key_len >> 2); - nkf = (int)((num_rounds + 1) << 2); - for (i = 0; i < nk; i ++) { - skey[i] = br_dec32be((const unsigned char *)key + (i << 2)); - } - for (i = nk, j = 0, k = 0; i < nkf; i ++) { - uint32_t tmp; - - tmp = skey[i - 1]; - if (j == 0) { - tmp = (tmp << 8) | (tmp >> 24); - tmp = SubWord(tmp) ^ Rcon[k]; - } else if (nk > 6 && j == 4) { - tmp = SubWord(tmp); - } - skey[i] = skey[i - nk] ^ tmp; - if (++ j == nk) { - j = 0; - k ++; - } - } - return num_rounds; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct.c b/src/tls/bearssl/aes_ct.c deleted file mode 100644 index 6e5ac5598..000000000 --- a/src/tls/bearssl/aes_ct.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_aes_ct_bitslice_Sbox(uint32_t *q) -{ - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint32_t x0, x1, x2, x3, x4, x5, x6, x7; - uint32_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21; - uint32_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint32_t z10, z11, z12, z13, z14, z15, z16, z17; - uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint32_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint32_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint32_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint32_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint32_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint32_t t60, t61, t62, t63, t64, t65, t66, t67; - uint32_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -/* see inner.h */ -void -br_aes_ct_ortho(uint32_t *q) -{ -#define SWAPN(cl, ch, s, x, y) do { \ - uint32_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint32_t)cl) | ((b & (uint32_t)cl) << (s)); \ - (y) = ((a & (uint32_t)ch) >> (s)) | (b & (uint32_t)ch); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x55555555, 0xAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x33333333, 0xCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F, 0xF0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - -static const unsigned char Rcon[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 -}; - -static uint32_t -sub_word(uint32_t x) -{ - uint32_t q[8]; - int i; - - for (i = 0; i < 8; i ++) { - q[i] = x; - } - br_aes_ct_ortho(q); - br_aes_ct_bitslice_Sbox(q); - br_aes_ct_ortho(q); - return q[0]; -} - -/* see inner.h */ -unsigned -br_aes_ct_keysched(uint32_t *comp_skey, const void *key, size_t key_len) -{ - unsigned num_rounds; - int i, j, k, nk, nkf; - uint32_t tmp; - uint32_t skey[120]; - - switch (key_len) { - case 16: - num_rounds = 10; - break; - case 24: - num_rounds = 12; - break; - case 32: - num_rounds = 14; - break; - default: - /* abort(); */ - return 0; - } - nk = (int)(key_len >> 2); - nkf = (int)((num_rounds + 1) << 2); - tmp = 0; - for (i = 0; i < nk; i ++) { - tmp = br_dec32le((const unsigned char *)key + (i << 2)); - skey[(i << 1) + 0] = tmp; - skey[(i << 1) + 1] = tmp; - } - for (i = nk, j = 0, k = 0; i < nkf; i ++) { - if (j == 0) { - tmp = (tmp << 24) | (tmp >> 8); - tmp = sub_word(tmp) ^ Rcon[k]; - } else if (nk > 6 && j == 4) { - tmp = sub_word(tmp); - } - tmp ^= skey[(i - nk) << 1]; - skey[(i << 1) + 0] = tmp; - skey[(i << 1) + 1] = tmp; - if (++ j == nk) { - j = 0; - k ++; - } - } - for (i = 0; i < nkf; i += 4) { - br_aes_ct_ortho(skey + (i << 1)); - } - for (i = 0, j = 0; i < nkf; i ++, j += 2) { - comp_skey[i] = (skey[j + 0] & 0x55555555) - | (skey[j + 1] & 0xAAAAAAAA); - } - return num_rounds; -} - -/* see inner.h */ -void -br_aes_ct_skey_expand(uint32_t *skey, - unsigned num_rounds, const uint32_t *comp_skey) -{ - unsigned u, v, n; - - n = (num_rounds + 1) << 2; - for (u = 0, v = 0; u < n; u ++, v += 2) { - uint32_t x, y; - - x = y = comp_skey[u]; - x &= 0x55555555; - skey[v + 0] = x | (x << 1); - y &= 0xAAAAAAAA; - skey[v + 1] = y | (y >> 1); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64.c b/src/tls/bearssl/aes_ct64.c deleted file mode 100644 index 99b650a39..000000000 --- a/src/tls/bearssl/aes_ct64.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_aes_ct64_bitslice_Sbox(uint64_t *q) -{ - /* - * This S-box implementation is a straightforward translation of - * the circuit described by Boyar and Peralta in "A new - * combinational logic minimization technique with applications - * to cryptology" (https://eprint.iacr.org/2009/191.pdf). - * - * Note that variables x* (input) and s* (output) are numbered - * in "reverse" order (x0 is the high bit, x7 is the low bit). - */ - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7; - uint64_t y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint64_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint64_t y20, y21; - uint64_t z0, z1, z2, z3, z4, z5, z6, z7, z8, z9; - uint64_t z10, z11, z12, z13, z14, z15, z16, z17; - uint64_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; - uint64_t t10, t11, t12, t13, t14, t15, t16, t17, t18, t19; - uint64_t t20, t21, t22, t23, t24, t25, t26, t27, t28, t29; - uint64_t t30, t31, t32, t33, t34, t35, t36, t37, t38, t39; - uint64_t t40, t41, t42, t43, t44, t45, t46, t47, t48, t49; - uint64_t t50, t51, t52, t53, t54, t55, t56, t57, t58, t59; - uint64_t t60, t61, t62, t63, t64, t65, t66, t67; - uint64_t s0, s1, s2, s3, s4, s5, s6, s7; - - x0 = q[7]; - x1 = q[6]; - x2 = q[5]; - x3 = q[4]; - x4 = q[3]; - x5 = q[2]; - x6 = q[1]; - x7 = q[0]; - - /* - * Top linear transformation. - */ - y14 = x3 ^ x5; - y13 = x0 ^ x6; - y9 = x0 ^ x3; - y8 = x0 ^ x5; - t0 = x1 ^ x2; - y1 = t0 ^ x7; - y4 = y1 ^ x3; - y12 = y13 ^ y14; - y2 = y1 ^ x0; - y5 = y1 ^ x6; - y3 = y5 ^ y8; - t1 = x4 ^ y12; - y15 = t1 ^ x5; - y20 = t1 ^ x1; - y6 = y15 ^ x7; - y10 = y15 ^ t0; - y11 = y20 ^ y9; - y7 = x7 ^ y11; - y17 = y10 ^ y11; - y19 = y10 ^ y8; - y16 = t0 ^ y11; - y21 = y13 ^ y16; - y18 = x0 ^ y16; - - /* - * Non-linear section. - */ - t2 = y12 & y15; - t3 = y3 & y6; - t4 = t3 ^ t2; - t5 = y4 & x7; - t6 = t5 ^ t2; - t7 = y13 & y16; - t8 = y5 & y1; - t9 = t8 ^ t7; - t10 = y2 & y7; - t11 = t10 ^ t7; - t12 = y9 & y11; - t13 = y14 & y17; - t14 = t13 ^ t12; - t15 = y8 & y10; - t16 = t15 ^ t12; - t17 = t4 ^ t14; - t18 = t6 ^ t16; - t19 = t9 ^ t14; - t20 = t11 ^ t16; - t21 = t17 ^ y20; - t22 = t18 ^ y19; - t23 = t19 ^ y21; - t24 = t20 ^ y18; - - t25 = t21 ^ t22; - t26 = t21 & t23; - t27 = t24 ^ t26; - t28 = t25 & t27; - t29 = t28 ^ t22; - t30 = t23 ^ t24; - t31 = t22 ^ t26; - t32 = t31 & t30; - t33 = t32 ^ t24; - t34 = t23 ^ t33; - t35 = t27 ^ t33; - t36 = t24 & t35; - t37 = t36 ^ t34; - t38 = t27 ^ t36; - t39 = t29 & t38; - t40 = t25 ^ t39; - - t41 = t40 ^ t37; - t42 = t29 ^ t33; - t43 = t29 ^ t40; - t44 = t33 ^ t37; - t45 = t42 ^ t41; - z0 = t44 & y15; - z1 = t37 & y6; - z2 = t33 & x7; - z3 = t43 & y16; - z4 = t40 & y1; - z5 = t29 & y7; - z6 = t42 & y11; - z7 = t45 & y17; - z8 = t41 & y10; - z9 = t44 & y12; - z10 = t37 & y3; - z11 = t33 & y4; - z12 = t43 & y13; - z13 = t40 & y5; - z14 = t29 & y2; - z15 = t42 & y9; - z16 = t45 & y14; - z17 = t41 & y8; - - /* - * Bottom linear transformation. - */ - t46 = z15 ^ z16; - t47 = z10 ^ z11; - t48 = z5 ^ z13; - t49 = z9 ^ z10; - t50 = z2 ^ z12; - t51 = z2 ^ z5; - t52 = z7 ^ z8; - t53 = z0 ^ z3; - t54 = z6 ^ z7; - t55 = z16 ^ z17; - t56 = z12 ^ t48; - t57 = t50 ^ t53; - t58 = z4 ^ t46; - t59 = z3 ^ t54; - t60 = t46 ^ t57; - t61 = z14 ^ t57; - t62 = t52 ^ t58; - t63 = t49 ^ t58; - t64 = z4 ^ t59; - t65 = t61 ^ t62; - t66 = z1 ^ t63; - s0 = t59 ^ t63; - s6 = t56 ^ ~t62; - s7 = t48 ^ ~t60; - t67 = t64 ^ t65; - s3 = t53 ^ t66; - s4 = t51 ^ t66; - s5 = t47 ^ t65; - s1 = t64 ^ ~s3; - s2 = t55 ^ ~t67; - - q[7] = s0; - q[6] = s1; - q[5] = s2; - q[4] = s3; - q[3] = s4; - q[2] = s5; - q[1] = s6; - q[0] = s7; -} - -/* see inner.h */ -void -br_aes_ct64_ortho(uint64_t *q) -{ -#define SWAPN(cl, ch, s, x, y) do { \ - uint64_t a, b; \ - a = (x); \ - b = (y); \ - (x) = (a & (uint64_t)cl) | ((b & (uint64_t)cl) << (s)); \ - (y) = ((a & (uint64_t)ch) >> (s)) | (b & (uint64_t)ch); \ - } while (0) - -#define SWAP2(x, y) SWAPN(0x5555555555555555, 0xAAAAAAAAAAAAAAAA, 1, x, y) -#define SWAP4(x, y) SWAPN(0x3333333333333333, 0xCCCCCCCCCCCCCCCC, 2, x, y) -#define SWAP8(x, y) SWAPN(0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0, 4, x, y) - - SWAP2(q[0], q[1]); - SWAP2(q[2], q[3]); - SWAP2(q[4], q[5]); - SWAP2(q[6], q[7]); - - SWAP4(q[0], q[2]); - SWAP4(q[1], q[3]); - SWAP4(q[4], q[6]); - SWAP4(q[5], q[7]); - - SWAP8(q[0], q[4]); - SWAP8(q[1], q[5]); - SWAP8(q[2], q[6]); - SWAP8(q[3], q[7]); -} - -/* see inner.h */ -void -br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w) -{ - uint64_t x0, x1, x2, x3; - - x0 = w[0]; - x1 = w[1]; - x2 = w[2]; - x3 = w[3]; - x0 |= (x0 << 16); - x1 |= (x1 << 16); - x2 |= (x2 << 16); - x3 |= (x3 << 16); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - x0 |= (x0 << 8); - x1 |= (x1 << 8); - x2 |= (x2 << 8); - x3 |= (x3 << 8); - x0 &= (uint64_t)0x00FF00FF00FF00FF; - x1 &= (uint64_t)0x00FF00FF00FF00FF; - x2 &= (uint64_t)0x00FF00FF00FF00FF; - x3 &= (uint64_t)0x00FF00FF00FF00FF; - *q0 = x0 | (x2 << 8); - *q1 = x1 | (x3 << 8); -} - -/* see inner.h */ -void -br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1) -{ - uint64_t x0, x1, x2, x3; - - x0 = q0 & (uint64_t)0x00FF00FF00FF00FF; - x1 = q1 & (uint64_t)0x00FF00FF00FF00FF; - x2 = (q0 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x3 = (q1 >> 8) & (uint64_t)0x00FF00FF00FF00FF; - x0 |= (x0 >> 8); - x1 |= (x1 >> 8); - x2 |= (x2 >> 8); - x3 |= (x3 >> 8); - x0 &= (uint64_t)0x0000FFFF0000FFFF; - x1 &= (uint64_t)0x0000FFFF0000FFFF; - x2 &= (uint64_t)0x0000FFFF0000FFFF; - x3 &= (uint64_t)0x0000FFFF0000FFFF; - w[0] = (uint32_t)x0 | (uint32_t)(x0 >> 16); - w[1] = (uint32_t)x1 | (uint32_t)(x1 >> 16); - w[2] = (uint32_t)x2 | (uint32_t)(x2 >> 16); - w[3] = (uint32_t)x3 | (uint32_t)(x3 >> 16); -} - -static const unsigned char Rcon[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 -}; - -static uint32_t -sub_word(uint32_t x) -{ - uint64_t q[8]; - - memset(q, 0, sizeof q); - q[0] = x; - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_Sbox(q); - br_aes_ct64_ortho(q); - return (uint32_t)q[0]; -} - -/* see inner.h */ -unsigned -br_aes_ct64_keysched(uint64_t *comp_skey, const void *key, size_t key_len) -{ - unsigned num_rounds; - int i, j, k, nk, nkf; - uint32_t tmp; - uint32_t skey[60]; - - switch (key_len) { - case 16: - num_rounds = 10; - break; - case 24: - num_rounds = 12; - break; - case 32: - num_rounds = 14; - break; - default: - /* abort(); */ - return 0; - } - nk = (int)(key_len >> 2); - nkf = (int)((num_rounds + 1) << 2); - br_range_dec32le(skey, (key_len >> 2), key); - tmp = skey[(key_len >> 2) - 1]; - for (i = nk, j = 0, k = 0; i < nkf; i ++) { - if (j == 0) { - tmp = (tmp << 24) | (tmp >> 8); - tmp = sub_word(tmp) ^ Rcon[k]; - } else if (nk > 6 && j == 4) { - tmp = sub_word(tmp); - } - tmp ^= skey[i - nk]; - skey[i] = tmp; - if (++ j == nk) { - j = 0; - k ++; - } - } - - for (i = 0, j = 0; i < nkf; i += 4, j += 2) { - uint64_t q[8]; - - br_aes_ct64_interleave_in(&q[0], &q[4], skey + i); - q[1] = q[0]; - q[2] = q[0]; - q[3] = q[0]; - q[5] = q[4]; - q[6] = q[4]; - q[7] = q[4]; - br_aes_ct64_ortho(q); - comp_skey[j + 0] = - (q[0] & (uint64_t)0x1111111111111111) - | (q[1] & (uint64_t)0x2222222222222222) - | (q[2] & (uint64_t)0x4444444444444444) - | (q[3] & (uint64_t)0x8888888888888888); - comp_skey[j + 1] = - (q[4] & (uint64_t)0x1111111111111111) - | (q[5] & (uint64_t)0x2222222222222222) - | (q[6] & (uint64_t)0x4444444444444444) - | (q[7] & (uint64_t)0x8888888888888888); - } - return num_rounds; -} - -/* see inner.h */ -void -br_aes_ct64_skey_expand(uint64_t *skey, - unsigned num_rounds, const uint64_t *comp_skey) -{ - unsigned u, v, n; - - n = (num_rounds + 1) << 1; - for (u = 0, v = 0; u < n; u ++, v += 4) { - uint64_t x0, x1, x2, x3; - - x0 = x1 = x2 = x3 = comp_skey[u]; - x0 &= (uint64_t)0x1111111111111111; - x1 &= (uint64_t)0x2222222222222222; - x2 &= (uint64_t)0x4444444444444444; - x3 &= (uint64_t)0x8888888888888888; - x1 >>= 1; - x2 >>= 2; - x3 >>= 3; - skey[v + 0] = (x0 << 4) - x0; - skey[v + 1] = (x1 << 4) - x1; - skey[v + 2] = (x2 << 4) - x2; - skey[v + 3] = (x3 << 4) - x3; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_cbcdec.c b/src/tls/bearssl/aes_ct64_cbcdec.c deleted file mode 100644 index 5f0f8185d..000000000 --- a/src/tls/bearssl/aes_ct64_cbcdec.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct64_cbcdec_vtable; - ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf; - uint64_t sk_exp[120]; - uint32_t ivw[4]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - br_range_dec32le(ivw, 4, iv); - buf = data; - while (len > 0) { - uint64_t q[8]; - uint32_t w1[16], w2[16]; - int i; - - if (len >= 64) { - br_range_dec32le(w1, 16, buf); - } else { - br_range_dec32le(w1, len >> 2, buf); - } - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_in( - &q[i], &q[i + 4], w1 + (i << 2)); - } - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_decrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out( - w2 + (i << 2), q[i], q[i + 4]); - } - for (i = 0; i < 4; i ++) { - w2[i] ^= ivw[i]; - } - if (len >= 64) { - for (i = 4; i < 16; i ++) { - w2[i] ^= w1[i - 4]; - } - memcpy(ivw, w1 + 12, sizeof ivw); - br_range_enc32le(buf, w2, 16); - } else { - int j; - - j = (int)(len >> 2); - for (i = 4; i < j; i ++) { - w2[i] ^= w1[i - 4]; - } - memcpy(ivw, w1 + j - 4, sizeof ivw); - br_range_enc32le(buf, w2, j); - break; - } - buf += 64; - len -= 64; - } - br_range_enc32le(iv, ivw, 4); -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable = { - sizeof(br_aes_ct64_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_ct64_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_ct64_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_cbcenc.c b/src/tls/bearssl/aes_ct64_cbcenc.c deleted file mode 100644 index 03ca04980..000000000 --- a/src/tls/bearssl/aes_ct64_cbcenc.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct64_cbcenc_vtable; - ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf; - uint64_t sk_exp[120]; - uint32_t ivw[4]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - br_range_dec32le(ivw, 4, iv); - buf = data; - while (len > 0) { - uint32_t w[4]; - uint64_t q[8]; - - w[0] = ivw[0] ^ br_dec32le(buf); - w[1] = ivw[1] ^ br_dec32le(buf + 4); - w[2] = ivw[2] ^ br_dec32le(buf + 8); - w[3] = ivw[3] ^ br_dec32le(buf + 12); - br_aes_ct64_interleave_in(&q[0], &q[4], w); - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - br_aes_ct64_interleave_out(w, q[0], q[4]); - memcpy(ivw, w, sizeof w); - br_enc32le(buf, w[0]); - br_enc32le(buf + 4, w[1]); - br_enc32le(buf + 8, w[2]); - br_enc32le(buf + 12, w[3]); - buf += 16; - len -= 16; - } - br_range_enc32le(iv, ivw, 4); -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable = { - sizeof(br_aes_ct64_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_ct64_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_ct64_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_ctr.c b/src/tls/bearssl/aes_ct64_ctr.c deleted file mode 100644 index e5e8bd01c..000000000 --- a/src/tls/bearssl/aes_ct64_ctr.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct64_ctr_vtable; - ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -uint32_t -br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - uint32_t ivw[16]; - uint64_t sk_exp[120]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - br_range_dec32le(ivw, 3, iv); - memcpy(ivw + 4, ivw, 3 * sizeof(uint32_t)); - memcpy(ivw + 8, ivw, 3 * sizeof(uint32_t)); - memcpy(ivw + 12, ivw, 3 * sizeof(uint32_t)); - buf = data; - while (len > 0) { - uint64_t q[8]; - uint32_t w[16]; - unsigned char tmp[64]; - int i; - - /* - * TODO: see if we can save on the first br_aes_ct64_ortho() - * call, since iv0/iv1/iv2 are constant for the whole run. - */ - memcpy(w, ivw, sizeof ivw); - w[3] = br_swap32(cc); - w[7] = br_swap32(cc + 1); - w[11] = br_swap32(cc + 2); - w[15] = br_swap32(cc + 3); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_in( - &q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out( - w + (i << 2), q[i], q[i + 4]); - } - br_range_enc32le(tmp, w, 16); - if (len <= 64) { - xorbuf(buf, tmp, len); - cc += (uint32_t)len >> 4; - break; - } - xorbuf(buf, tmp, 64); - buf += 64; - len -= 64; - cc += 4; - } - return cc; -} - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_ct64_ctr_vtable = { - sizeof(br_aes_ct64_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_ct64_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_ct64_ctr_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_ctrcbc.c b/src/tls/bearssl/aes_ct64_ctrcbc.c deleted file mode 100644 index 6930a78a1..000000000 --- a/src/tls/bearssl/aes_ct64_ctrcbc.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct64_ctrcbc_vtable; - ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -void -br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len) -{ - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint64_t sk_exp[120]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - buf = data; - while (len > 0) { - uint64_t q[8]; - uint32_t w[16]; - unsigned char tmp[64]; - int i, j; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - j = (len >= 64) ? 16 : (int)(len >> 2); - for (i = 0; i < j; i += 4) { - uint32_t carry; - - w[i + 0] = br_swap32(iv0); - w[i + 1] = br_swap32(iv1); - w[i + 2] = br_swap32(iv2); - w[i + 3] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - } - memset(w + i, 0, (16 - i) * sizeof(uint32_t)); - - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_in( - &q[i], &q[i + 4], w + (i << 2)); - } - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - for (i = 0; i < 4; i ++) { - br_aes_ct64_interleave_out( - w + (i << 2), q[i], q[i + 4]); - } - - br_range_enc32le(tmp, w, 16); - if (len <= 64) { - xorbuf(buf, tmp, len); - break; - } - xorbuf(buf, tmp, 64); - buf += 64; - len -= 64; - } - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); -} - -/* see bearssl_block.h */ -void -br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len) -{ - const unsigned char *buf; - uint32_t cm0, cm1, cm2, cm3; - uint64_t q[8]; - uint64_t sk_exp[120]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - - buf = data; - memset(q, 0, sizeof q); - while (len > 0) { - uint32_t w[4]; - - w[0] = cm0 ^ br_dec32le(buf + 0); - w[1] = cm1 ^ br_dec32le(buf + 4); - w[2] = cm2 ^ br_dec32le(buf + 8); - w[3] = cm3 ^ br_dec32le(buf + 12); - - br_aes_ct64_interleave_in(&q[0], &q[4], w); - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - br_aes_ct64_interleave_out(w, q[0], q[4]); - - cm0 = w[0]; - cm1 = w[1]; - cm2 = w[2]; - cm3 = w[3]; - buf += 16; - len -= 16; - } - - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -void -br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - /* - * When encrypting, the CBC-MAC processing must be lagging by - * one block, since it operates on the encrypted values, so - * it must wait for that encryption to complete. - */ - - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t cm0, cm1, cm2, cm3; - uint64_t sk_exp[120]; - uint64_t q[8]; - int first_iter; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - /* - * The current CBC-MAC value is kept in little-endian convention. - */ - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - - buf = data; - first_iter = 1; - memset(q, 0, sizeof q); - while (len > 0) { - uint32_t w[8], carry; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - w[0] = br_swap32(iv0); - w[1] = br_swap32(iv1); - w[2] = br_swap32(iv2); - w[3] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - - /* - * The block for CBC-MAC. - */ - w[4] = cm0; - w[5] = cm1; - w[6] = cm2; - w[7] = cm3; - - br_aes_ct64_interleave_in(&q[0], &q[4], w); - br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - br_aes_ct64_interleave_out(w, q[0], q[4]); - br_aes_ct64_interleave_out(w + 4, q[1], q[5]); - - /* - * We do the XOR with the plaintext in 32-bit registers, - * so that the value are available for CBC-MAC processing - * as well. - */ - w[0] ^= br_dec32le(buf + 0); - w[1] ^= br_dec32le(buf + 4); - w[2] ^= br_dec32le(buf + 8); - w[3] ^= br_dec32le(buf + 12); - br_enc32le(buf + 0, w[0]); - br_enc32le(buf + 4, w[1]); - br_enc32le(buf + 8, w[2]); - br_enc32le(buf + 12, w[3]); - - buf += 16; - len -= 16; - - /* - * We set the cm* values to the block to encrypt in the - * next iteration. - */ - if (first_iter) { - first_iter = 0; - cm0 ^= w[0]; - cm1 ^= w[1]; - cm2 ^= w[2]; - cm3 ^= w[3]; - } else { - cm0 = w[0] ^ w[4]; - cm1 = w[1] ^ w[5]; - cm2 = w[2] ^ w[6]; - cm3 = w[3] ^ w[7]; - } - - /* - * If this was the last iteration, then compute the - * extra block encryption to complete CBC-MAC. - */ - if (len == 0) { - w[0] = cm0; - w[1] = cm1; - w[2] = cm2; - w[3] = cm3; - br_aes_ct64_interleave_in(&q[0], &q[4], w); - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt( - ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - br_aes_ct64_interleave_out(w, q[0], q[4]); - cm0 = w[0]; - cm1 = w[1]; - cm2 = w[2]; - cm3 = w[3]; - break; - } - } - - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -void -br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t cm0, cm1, cm2, cm3; - uint64_t sk_exp[120]; - uint64_t q[8]; - - br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - /* - * The current CBC-MAC value is kept in little-endian convention. - */ - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - - buf = data; - memset(q, 0, sizeof q); - while (len > 0) { - uint32_t w[8], carry; - unsigned char tmp[16]; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - w[0] = br_swap32(iv0); - w[1] = br_swap32(iv1); - w[2] = br_swap32(iv2); - w[3] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - - /* - * The block for CBC-MAC. - */ - w[4] = cm0 ^ br_dec32le(buf + 0); - w[5] = cm1 ^ br_dec32le(buf + 4); - w[6] = cm2 ^ br_dec32le(buf + 8); - w[7] = cm3 ^ br_dec32le(buf + 12); - - br_aes_ct64_interleave_in(&q[0], &q[4], w); - br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); - br_aes_ct64_ortho(q); - br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct64_ortho(q); - br_aes_ct64_interleave_out(w, q[0], q[4]); - br_aes_ct64_interleave_out(w + 4, q[1], q[5]); - - br_enc32le(tmp + 0, w[0]); - br_enc32le(tmp + 4, w[1]); - br_enc32le(tmp + 8, w[2]); - br_enc32le(tmp + 12, w[3]); - xorbuf(buf, tmp, 16); - cm0 = w[4]; - cm1 = w[5]; - cm2 = w[6]; - cm3 = w[7]; - buf += 16; - len -= 16; - } - - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable = { - sizeof(br_aes_ct64_ctrcbc_keys), - 16, - 4, - (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) - &br_aes_ct64_ctrcbc_init, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_ct64_ctrcbc_encrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_ct64_ctrcbc_decrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, size_t)) - &br_aes_ct64_ctrcbc_ctr, - (void (*)(const br_block_ctrcbc_class *const *, - void *, const void *, size_t)) - &br_aes_ct64_ctrcbc_mac -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_dec.c b/src/tls/bearssl/aes_ct64_dec.c deleted file mode 100644 index 971d380b8..000000000 --- a/src/tls/bearssl/aes_ct64_dec.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_aes_ct64_bitslice_invSbox(uint64_t *q) -{ - /* - * See br_aes_ct_bitslice_invSbox(). This is the natural extension - * to 64-bit registers. - */ - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - - q0 = ~q[0]; - q1 = ~q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = ~q[5]; - q6 = ~q[6]; - q7 = q[7]; - q[7] = q1 ^ q4 ^ q6; - q[6] = q0 ^ q3 ^ q5; - q[5] = q7 ^ q2 ^ q4; - q[4] = q6 ^ q1 ^ q3; - q[3] = q5 ^ q0 ^ q2; - q[2] = q4 ^ q7 ^ q1; - q[1] = q3 ^ q6 ^ q0; - q[0] = q2 ^ q5 ^ q7; - - br_aes_ct64_bitslice_Sbox(q); - - q0 = ~q[0]; - q1 = ~q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = ~q[5]; - q6 = ~q[6]; - q7 = q[7]; - q[7] = q1 ^ q4 ^ q6; - q[6] = q0 ^ q3 ^ q5; - q[5] = q7 ^ q2 ^ q4; - q[4] = q6 ^ q1 ^ q3; - q[3] = q5 ^ q0 ^ q2; - q[2] = q4 ^ q7 ^ q1; - q[1] = q3 ^ q6 ^ q0; - q[0] = q2 ^ q5 ^ q7; -} - -static void -add_round_key(uint64_t *q, const uint64_t *sk) -{ - int i; - - for (i = 0; i < 8; i ++) { - q[i] ^= sk[i]; - } -} - -static void -inv_shift_rows(uint64_t *q) -{ - int i; - - for (i = 0; i < 8; i ++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x000000000FFF0000) << 4) - | ((x & (uint64_t)0x00000000F0000000) >> 12) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000F000000000000) << 12) - | ((x & (uint64_t)0xFFF0000000000000) >> 4); - } -} - -static inline uint64_t -rotr32(uint64_t x) -{ - return (x << 32) | (x >> 32); -} - -static void -inv_mix_columns(uint64_t *q) -{ - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr32(q0 ^ q5 ^ q6 ^ r0 ^ r5); - q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6); - q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr32(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7); - q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr32(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7); - q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6); - q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr32(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7); - q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr32(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7); - q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr32(q4 ^ q5 ^ q7 ^ r4 ^ r7); -} - -/* see inner.h */ -void -br_aes_ct64_bitslice_decrypt(unsigned num_rounds, - const uint64_t *skey, uint64_t *q) -{ - unsigned u; - - add_round_key(q, skey + (num_rounds << 3)); - for (u = num_rounds - 1; u > 0; u --) { - inv_shift_rows(q); - br_aes_ct64_bitslice_invSbox(q); - add_round_key(q, skey + (u << 3)); - inv_mix_columns(q); - } - inv_shift_rows(q); - br_aes_ct64_bitslice_invSbox(q); - add_round_key(q, skey); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct64_enc.c b/src/tls/bearssl/aes_ct64_enc.c deleted file mode 100644 index 6468f91e9..000000000 --- a/src/tls/bearssl/aes_ct64_enc.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static inline void -add_round_key(uint64_t *q, const uint64_t *sk) -{ - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void -shift_rows(uint64_t *q) -{ - int i; - - for (i = 0; i < 8; i ++) { - uint64_t x; - - x = q[i]; - q[i] = (x & (uint64_t)0x000000000000FFFF) - | ((x & (uint64_t)0x00000000FFF00000) >> 4) - | ((x & (uint64_t)0x00000000000F0000) << 12) - | ((x & (uint64_t)0x0000FF0000000000) >> 8) - | ((x & (uint64_t)0x000000FF00000000) << 8) - | ((x & (uint64_t)0xF000000000000000) >> 12) - | ((x & (uint64_t)0x0FFF000000000000) << 4); - } -} - -static inline uint64_t -rotr32(uint64_t x) -{ - return (x << 32) | (x >> 32); -} - -static inline void -mix_columns(uint64_t *q) -{ - uint64_t q0, q1, q2, q3, q4, q5, q6, q7; - uint64_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 16) | (q0 << 48); - r1 = (q1 >> 16) | (q1 << 48); - r2 = (q2 >> 16) | (q2 << 48); - r3 = (q3 >> 16) | (q3 << 48); - r4 = (q4 >> 16) | (q4 << 48); - r5 = (q5 >> 16) | (q5 << 48); - r6 = (q6 >> 16) | (q6 << 48); - r7 = (q7 >> 16) | (q7 << 48); - - q[0] = q7 ^ r7 ^ r0 ^ rotr32(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr32(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr32(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr32(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr32(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr32(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr32(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7); -} - -/* see inner.h */ -void -br_aes_ct64_bitslice_encrypt(unsigned num_rounds, - const uint64_t *skey, uint64_t *q) -{ - unsigned u; - - add_round_key(q, skey); - for (u = 1; u < num_rounds; u ++) { - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, skey + (u << 3)); - } - br_aes_ct64_bitslice_Sbox(q); - shift_rows(q); - add_round_key(q, skey + (num_rounds << 3)); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_cbcdec.c b/src/tls/bearssl/aes_ct_cbcdec.c deleted file mode 100644 index cb3d3ca72..000000000 --- a/src/tls/bearssl/aes_ct_cbcdec.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct_cbcdec_vtable; - ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t sk_exp[120]; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - ivbuf = iv; - iv0 = br_dec32le(ivbuf); - iv1 = br_dec32le(ivbuf + 4); - iv2 = br_dec32le(ivbuf + 8); - iv3 = br_dec32le(ivbuf + 12); - buf = data; - while (len > 0) { - uint32_t q[8], sq[8]; - - q[0] = br_dec32le(buf); - q[2] = br_dec32le(buf + 4); - q[4] = br_dec32le(buf + 8); - q[6] = br_dec32le(buf + 12); - if (len >= 32) { - q[1] = br_dec32le(buf + 16); - q[3] = br_dec32le(buf + 20); - q[5] = br_dec32le(buf + 24); - q[7] = br_dec32le(buf + 28); - } else { - q[1] = 0; - q[3] = 0; - q[5] = 0; - q[7] = 0; - } - memcpy(sq, q, sizeof q); - br_aes_ct_ortho(q); - br_aes_ct_bitslice_decrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - br_enc32le(buf, q[0] ^ iv0); - br_enc32le(buf + 4, q[2] ^ iv1); - br_enc32le(buf + 8, q[4] ^ iv2); - br_enc32le(buf + 12, q[6] ^ iv3); - if (len < 32) { - iv0 = sq[0]; - iv1 = sq[2]; - iv2 = sq[4]; - iv3 = sq[6]; - break; - } - br_enc32le(buf + 16, q[1] ^ sq[0]); - br_enc32le(buf + 20, q[3] ^ sq[2]); - br_enc32le(buf + 24, q[5] ^ sq[4]); - br_enc32le(buf + 28, q[7] ^ sq[6]); - iv0 = sq[1]; - iv1 = sq[3]; - iv2 = sq[5]; - iv3 = sq[7]; - buf += 32; - len -= 32; - } - br_enc32le(ivbuf, iv0); - br_enc32le(ivbuf + 4, iv1); - br_enc32le(ivbuf + 8, iv2); - br_enc32le(ivbuf + 12, iv3); -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_ct_cbcdec_vtable = { - sizeof(br_aes_ct_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_ct_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_ct_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_cbcenc.c b/src/tls/bearssl/aes_ct_cbcenc.c deleted file mode 100644 index 343db500b..000000000 --- a/src/tls/bearssl/aes_ct_cbcenc.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct_cbcenc_vtable; - ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - uint32_t q[8]; - uint32_t iv0, iv1, iv2, iv3; - uint32_t sk_exp[120]; - - q[1] = 0; - q[3] = 0; - q[5] = 0; - q[7] = 0; - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - ivbuf = iv; - iv0 = br_dec32le(ivbuf); - iv1 = br_dec32le(ivbuf + 4); - iv2 = br_dec32le(ivbuf + 8); - iv3 = br_dec32le(ivbuf + 12); - buf = data; - while (len > 0) { - q[0] = iv0 ^ br_dec32le(buf); - q[2] = iv1 ^ br_dec32le(buf + 4); - q[4] = iv2 ^ br_dec32le(buf + 8); - q[6] = iv3 ^ br_dec32le(buf + 12); - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - iv0 = q[0]; - iv1 = q[2]; - iv2 = q[4]; - iv3 = q[6]; - br_enc32le(buf, iv0); - br_enc32le(buf + 4, iv1); - br_enc32le(buf + 8, iv2); - br_enc32le(buf + 12, iv3); - buf += 16; - len -= 16; - } - br_enc32le(ivbuf, iv0); - br_enc32le(ivbuf + 4, iv1); - br_enc32le(ivbuf + 8, iv2); - br_enc32le(ivbuf + 12, iv3); -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_ct_cbcenc_vtable = { - sizeof(br_aes_ct_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_ct_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_ct_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_ctr.c b/src/tls/bearssl/aes_ct_ctr.c deleted file mode 100644 index 820e595f0..000000000 --- a/src/tls/bearssl/aes_ct_ctr.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct_ctr_vtable; - ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -uint32_t -br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - const unsigned char *ivbuf; - uint32_t iv0, iv1, iv2; - uint32_t sk_exp[120]; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - ivbuf = iv; - iv0 = br_dec32le(ivbuf); - iv1 = br_dec32le(ivbuf + 4); - iv2 = br_dec32le(ivbuf + 8); - buf = data; - while (len > 0) { - uint32_t q[8]; - unsigned char tmp[32]; - - /* - * TODO: see if we can save on the first br_aes_ct_ortho() - * call, since iv0/iv1/iv2 are constant for the whole run. - */ - q[0] = q[1] = iv0; - q[2] = q[3] = iv1; - q[4] = q[5] = iv2; - q[6] = br_swap32(cc); - q[7] = br_swap32(cc + 1); - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - br_enc32le(tmp, q[0]); - br_enc32le(tmp + 4, q[2]); - br_enc32le(tmp + 8, q[4]); - br_enc32le(tmp + 12, q[6]); - br_enc32le(tmp + 16, q[1]); - br_enc32le(tmp + 20, q[3]); - br_enc32le(tmp + 24, q[5]); - br_enc32le(tmp + 28, q[7]); - - if (len <= 32) { - xorbuf(buf, tmp, len); - cc ++; - if (len > 16) { - cc ++; - } - break; - } - xorbuf(buf, tmp, 32); - buf += 32; - len -= 32; - cc += 2; - } - return cc; -} - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_ct_ctr_vtable = { - sizeof(br_aes_ct_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_ct_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_ct_ctr_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_ctrcbc.c b/src/tls/bearssl/aes_ct_ctrcbc.c deleted file mode 100644 index e3a2d0df7..000000000 --- a/src/tls/bearssl/aes_ct_ctrcbc.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_ct_ctrcbc_vtable; - ctx->num_rounds = br_aes_ct_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -void -br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len) -{ - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t sk_exp[120]; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - buf = data; - while (len > 0) { - uint32_t q[8], carry; - unsigned char tmp[32]; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - q[0] = br_swap32(iv0); - q[2] = br_swap32(iv1); - q[4] = br_swap32(iv2); - q[6] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - q[1] = br_swap32(iv0); - q[3] = br_swap32(iv1); - q[5] = br_swap32(iv2); - q[7] = br_swap32(iv3); - if (len > 16) { - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - } - - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - - br_enc32le(tmp, q[0]); - br_enc32le(tmp + 4, q[2]); - br_enc32le(tmp + 8, q[4]); - br_enc32le(tmp + 12, q[6]); - br_enc32le(tmp + 16, q[1]); - br_enc32le(tmp + 20, q[3]); - br_enc32le(tmp + 24, q[5]); - br_enc32le(tmp + 28, q[7]); - - if (len <= 32) { - xorbuf(buf, tmp, len); - break; - } - xorbuf(buf, tmp, 32); - buf += 32; - len -= 32; - } - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); -} - -/* see bearssl_block.h */ -void -br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len) -{ - const unsigned char *buf; - uint32_t cm0, cm1, cm2, cm3; - uint32_t q[8]; - uint32_t sk_exp[120]; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - buf = data; - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - q[1] = 0; - q[3] = 0; - q[5] = 0; - q[7] = 0; - - while (len > 0) { - q[0] = cm0 ^ br_dec32le(buf + 0); - q[2] = cm1 ^ br_dec32le(buf + 4); - q[4] = cm2 ^ br_dec32le(buf + 8); - q[6] = cm3 ^ br_dec32le(buf + 12); - - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - - cm0 = q[0]; - cm1 = q[2]; - cm2 = q[4]; - cm3 = q[6]; - buf += 16; - len -= 16; - } - - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -void -br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - /* - * When encrypting, the CBC-MAC processing must be lagging by - * one block, since it operates on the encrypted values, so - * it must wait for that encryption to complete. - */ - - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t cm0, cm1, cm2, cm3; - uint32_t sk_exp[120]; - int first_iter; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - /* - * The current CBC-MAC value is kept in little-endian convention. - */ - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - - buf = data; - first_iter = 1; - while (len > 0) { - uint32_t q[8], carry; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - q[0] = br_swap32(iv0); - q[2] = br_swap32(iv1); - q[4] = br_swap32(iv2); - q[6] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - - /* - * The odd values are used for CBC-MAC. - */ - q[1] = cm0; - q[3] = cm1; - q[5] = cm2; - q[7] = cm3; - - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - - /* - * We do the XOR with the plaintext in 32-bit registers, - * so that the value are available for CBC-MAC processing - * as well. - */ - q[0] ^= br_dec32le(buf + 0); - q[2] ^= br_dec32le(buf + 4); - q[4] ^= br_dec32le(buf + 8); - q[6] ^= br_dec32le(buf + 12); - br_enc32le(buf + 0, q[0]); - br_enc32le(buf + 4, q[2]); - br_enc32le(buf + 8, q[4]); - br_enc32le(buf + 12, q[6]); - - buf += 16; - len -= 16; - - /* - * We set the cm* values to the block to encrypt in the - * next iteration. - */ - if (first_iter) { - first_iter = 0; - cm0 ^= q[0]; - cm1 ^= q[2]; - cm2 ^= q[4]; - cm3 ^= q[6]; - } else { - cm0 = q[0] ^ q[1]; - cm1 = q[2] ^ q[3]; - cm2 = q[4] ^ q[5]; - cm3 = q[6] ^ q[7]; - } - - /* - * If this was the last iteration, then compute the - * extra block encryption to complete CBC-MAC. - */ - if (len == 0) { - q[0] = cm0; - q[2] = cm1; - q[4] = cm2; - q[6] = cm3; - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - cm0 = q[0]; - cm1 = q[2]; - cm2 = q[4]; - cm3 = q[6]; - break; - } - } - - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -void -br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - unsigned char *buf; - unsigned char *ivbuf; - uint32_t iv0, iv1, iv2, iv3; - uint32_t cm0, cm1, cm2, cm3; - uint32_t sk_exp[120]; - - br_aes_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - - /* - * We keep the counter as four 32-bit values, with big-endian - * convention, because that's what is expected for purposes of - * incrementing the counter value. - */ - ivbuf = ctr; - iv0 = br_dec32be(ivbuf + 0); - iv1 = br_dec32be(ivbuf + 4); - iv2 = br_dec32be(ivbuf + 8); - iv3 = br_dec32be(ivbuf + 12); - - /* - * The current CBC-MAC value is kept in little-endian convention. - */ - cm0 = br_dec32le((unsigned char *)cbcmac + 0); - cm1 = br_dec32le((unsigned char *)cbcmac + 4); - cm2 = br_dec32le((unsigned char *)cbcmac + 8); - cm3 = br_dec32le((unsigned char *)cbcmac + 12); - - buf = data; - while (len > 0) { - uint32_t q[8], carry; - unsigned char tmp[16]; - - /* - * The bitslice implementation expects values in - * little-endian convention, so we have to byteswap them. - */ - q[0] = br_swap32(iv0); - q[2] = br_swap32(iv1); - q[4] = br_swap32(iv2); - q[6] = br_swap32(iv3); - iv3 ++; - carry = ~(iv3 | -iv3) >> 31; - iv2 += carry; - carry &= -(~(iv2 | -iv2) >> 31); - iv1 += carry; - carry &= -(~(iv1 | -iv1) >> 31); - iv0 += carry; - - /* - * The odd values are used for CBC-MAC. - */ - q[1] = cm0 ^ br_dec32le(buf + 0); - q[3] = cm1 ^ br_dec32le(buf + 4); - q[5] = cm2 ^ br_dec32le(buf + 8); - q[7] = cm3 ^ br_dec32le(buf + 12); - - br_aes_ct_ortho(q); - br_aes_ct_bitslice_encrypt(ctx->num_rounds, sk_exp, q); - br_aes_ct_ortho(q); - - br_enc32le(tmp + 0, q[0]); - br_enc32le(tmp + 4, q[2]); - br_enc32le(tmp + 8, q[4]); - br_enc32le(tmp + 12, q[6]); - xorbuf(buf, tmp, 16); - cm0 = q[1]; - cm1 = q[3]; - cm2 = q[5]; - cm3 = q[7]; - buf += 16; - len -= 16; - } - - br_enc32be(ivbuf + 0, iv0); - br_enc32be(ivbuf + 4, iv1); - br_enc32be(ivbuf + 8, iv2); - br_enc32be(ivbuf + 12, iv3); - br_enc32le((unsigned char *)cbcmac + 0, cm0); - br_enc32le((unsigned char *)cbcmac + 4, cm1); - br_enc32le((unsigned char *)cbcmac + 8, cm2); - br_enc32le((unsigned char *)cbcmac + 12, cm3); -} - -/* see bearssl_block.h */ -const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable = { - sizeof(br_aes_ct_ctrcbc_keys), - 16, - 4, - (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) - &br_aes_ct_ctrcbc_init, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_ct_ctrcbc_encrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_ct_ctrcbc_decrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, size_t)) - &br_aes_ct_ctrcbc_ctr, - (void (*)(const br_block_ctrcbc_class *const *, - void *, const void *, size_t)) - &br_aes_ct_ctrcbc_mac -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_dec.c b/src/tls/bearssl/aes_ct_dec.c deleted file mode 100644 index 9564fd1bd..000000000 --- a/src/tls/bearssl/aes_ct_dec.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_aes_ct_bitslice_invSbox(uint32_t *q) -{ - /* - * AES S-box is: - * S(x) = A(I(x)) ^ 0x63 - * where I() is inversion in GF(256), and A() is a linear - * transform (0 is formally defined to be its own inverse). - * Since inversion is an involution, the inverse S-box can be - * computed from the S-box as: - * iS(x) = B(S(B(x ^ 0x63)) ^ 0x63) - * where B() is the inverse of A(). Indeed, for any y in GF(256): - * iS(S(y)) = B(A(I(B(A(I(y)) ^ 0x63 ^ 0x63))) ^ 0x63 ^ 0x63) = y - * - * Note: we reuse the implementation of the forward S-box, - * instead of duplicating it here, so that total code size is - * lower. By merging the B() transforms into the S-box circuit - * we could make faster CBC decryption, but CBC decryption is - * already quite faster than CBC encryption because we can - * process two blocks in parallel. - */ - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - - q0 = ~q[0]; - q1 = ~q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = ~q[5]; - q6 = ~q[6]; - q7 = q[7]; - q[7] = q1 ^ q4 ^ q6; - q[6] = q0 ^ q3 ^ q5; - q[5] = q7 ^ q2 ^ q4; - q[4] = q6 ^ q1 ^ q3; - q[3] = q5 ^ q0 ^ q2; - q[2] = q4 ^ q7 ^ q1; - q[1] = q3 ^ q6 ^ q0; - q[0] = q2 ^ q5 ^ q7; - - br_aes_ct_bitslice_Sbox(q); - - q0 = ~q[0]; - q1 = ~q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = ~q[5]; - q6 = ~q[6]; - q7 = q[7]; - q[7] = q1 ^ q4 ^ q6; - q[6] = q0 ^ q3 ^ q5; - q[5] = q7 ^ q2 ^ q4; - q[4] = q6 ^ q1 ^ q3; - q[3] = q5 ^ q0 ^ q2; - q[2] = q4 ^ q7 ^ q1; - q[1] = q3 ^ q6 ^ q0; - q[0] = q2 ^ q5 ^ q7; -} - -static void -add_round_key(uint32_t *q, const uint32_t *sk) -{ - int i; - - for (i = 0; i < 8; i ++) { - q[i] ^= sk[i]; - } -} - -static void -inv_shift_rows(uint32_t *q) -{ - int i; - - for (i = 0; i < 8; i ++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x00003F00) << 2) | ((x & 0x0000C000) >> 6) - | ((x & 0x000F0000) << 4) | ((x & 0x00F00000) >> 4) - | ((x & 0x03000000) << 6) | ((x & 0xFC000000) >> 2); - } -} - -static inline uint32_t -rotr16(uint32_t x) -{ - return (x << 16) | (x >> 16); -} - -static void -inv_mix_columns(uint32_t *q) -{ - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q5 ^ q6 ^ q7 ^ r0 ^ r5 ^ r7 ^ rotr16(q0 ^ q5 ^ q6 ^ r0 ^ r5); - q[1] = q0 ^ q5 ^ r0 ^ r1 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q5 ^ q7 ^ r1 ^ r5 ^ r6); - q[2] = q0 ^ q1 ^ q6 ^ r1 ^ r2 ^ r6 ^ r7 ^ rotr16(q0 ^ q2 ^ q6 ^ r2 ^ r6 ^ r7); - q[3] = q0 ^ q1 ^ q2 ^ q5 ^ q6 ^ r0 ^ r2 ^ r3 ^ r5 ^ rotr16(q0 ^ q1 ^ q3 ^ q5 ^ q6 ^ q7 ^ r0 ^ r3 ^ r5 ^ r7); - q[4] = q1 ^ q2 ^ q3 ^ q5 ^ r1 ^ r3 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q1 ^ q2 ^ q4 ^ q5 ^ q7 ^ r1 ^ r4 ^ r5 ^ r6); - q[5] = q2 ^ q3 ^ q4 ^ q6 ^ r2 ^ r4 ^ r5 ^ r6 ^ r7 ^ rotr16(q2 ^ q3 ^ q5 ^ q6 ^ r2 ^ r5 ^ r6 ^ r7); - q[6] = q3 ^ q4 ^ q5 ^ q7 ^ r3 ^ r5 ^ r6 ^ r7 ^ rotr16(q3 ^ q4 ^ q6 ^ q7 ^ r3 ^ r6 ^ r7); - q[7] = q4 ^ q5 ^ q6 ^ r4 ^ r6 ^ r7 ^ rotr16(q4 ^ q5 ^ q7 ^ r4 ^ r7); -} - -/* see inner.h */ -void -br_aes_ct_bitslice_decrypt(unsigned num_rounds, - const uint32_t *skey, uint32_t *q) -{ - unsigned u; - - add_round_key(q, skey + (num_rounds << 3)); - for (u = num_rounds - 1; u > 0; u --) { - inv_shift_rows(q); - br_aes_ct_bitslice_invSbox(q); - add_round_key(q, skey + (u << 3)); - inv_mix_columns(q); - } - inv_shift_rows(q); - br_aes_ct_bitslice_invSbox(q); - add_round_key(q, skey); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_ct_enc.c b/src/tls/bearssl/aes_ct_enc.c deleted file mode 100644 index a4cf32635..000000000 --- a/src/tls/bearssl/aes_ct_enc.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static inline void -add_round_key(uint32_t *q, const uint32_t *sk) -{ - q[0] ^= sk[0]; - q[1] ^= sk[1]; - q[2] ^= sk[2]; - q[3] ^= sk[3]; - q[4] ^= sk[4]; - q[5] ^= sk[5]; - q[6] ^= sk[6]; - q[7] ^= sk[7]; -} - -static inline void -shift_rows(uint32_t *q) -{ - int i; - - for (i = 0; i < 8; i ++) { - uint32_t x; - - x = q[i]; - q[i] = (x & 0x000000FF) - | ((x & 0x0000FC00) >> 2) | ((x & 0x00000300) << 6) - | ((x & 0x00F00000) >> 4) | ((x & 0x000F0000) << 4) - | ((x & 0xC0000000) >> 6) | ((x & 0x3F000000) << 2); - } -} - -static inline uint32_t -rotr16(uint32_t x) -{ - return (x << 16) | (x >> 16); -} - -static inline void -mix_columns(uint32_t *q) -{ - uint32_t q0, q1, q2, q3, q4, q5, q6, q7; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7; - - q0 = q[0]; - q1 = q[1]; - q2 = q[2]; - q3 = q[3]; - q4 = q[4]; - q5 = q[5]; - q6 = q[6]; - q7 = q[7]; - r0 = (q0 >> 8) | (q0 << 24); - r1 = (q1 >> 8) | (q1 << 24); - r2 = (q2 >> 8) | (q2 << 24); - r3 = (q3 >> 8) | (q3 << 24); - r4 = (q4 >> 8) | (q4 << 24); - r5 = (q5 >> 8) | (q5 << 24); - r6 = (q6 >> 8) | (q6 << 24); - r7 = (q7 >> 8) | (q7 << 24); - - q[0] = q7 ^ r7 ^ r0 ^ rotr16(q0 ^ r0); - q[1] = q0 ^ r0 ^ q7 ^ r7 ^ r1 ^ rotr16(q1 ^ r1); - q[2] = q1 ^ r1 ^ r2 ^ rotr16(q2 ^ r2); - q[3] = q2 ^ r2 ^ q7 ^ r7 ^ r3 ^ rotr16(q3 ^ r3); - q[4] = q3 ^ r3 ^ q7 ^ r7 ^ r4 ^ rotr16(q4 ^ r4); - q[5] = q4 ^ r4 ^ r5 ^ rotr16(q5 ^ r5); - q[6] = q5 ^ r5 ^ r6 ^ rotr16(q6 ^ r6); - q[7] = q6 ^ r6 ^ r7 ^ rotr16(q7 ^ r7); -} - -/* see inner.h */ -void -br_aes_ct_bitslice_encrypt(unsigned num_rounds, - const uint32_t *skey, uint32_t *q) -{ - unsigned u; - - add_round_key(q, skey); - for (u = 1; u < num_rounds; u ++) { - br_aes_ct_bitslice_Sbox(q); - shift_rows(q); - mix_columns(q); - add_round_key(q, skey + (u << 3)); - } - br_aes_ct_bitslice_Sbox(q); - shift_rows(q); - add_round_key(q, skey + (num_rounds << 3)); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_pwr8.c b/src/tls/bearssl/aes_pwr8.c deleted file mode 100644 index eae3ce3b0..000000000 --- a/src/tls/bearssl/aes_pwr8.c +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -/* - * This code contains the AES key schedule implementation using the - * POWER8 opcodes. - */ - -#if BR_POWER8 - -static void -key_schedule_128(unsigned char *sk, const unsigned char *key) -{ - long cc; - - static const uint32_t fmod[] = { 0x11B, 0x11B, 0x11B, 0x11B }; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - - /* - * We use the VSX instructions for loading and storing the - * key/subkeys, since they support unaligned accesses. The rest - * of the computation is VMX only. VMX register 0 is VSX - * register 32. - */ - asm volatile ( - - /* - * v0 = all-zero word - * v1 = constant -8 / +8, copied into four words - * v2 = current subkey - * v3 = Rcon (x4 words) - * v6 = constant 8, copied into four words - * v7 = constant 0x11B, copied into four words - * v8 = constant for byteswapping words - */ - vspltisw(0, 0) -#if BR_POWER8_LE - vspltisw(1, -8) -#else - vspltisw(1, 8) -#endif - lxvw4x(34, 0, %[key]) - vspltisw(3, 1) - vspltisw(6, 8) - lxvw4x(39, 0, %[fmod]) -#if BR_POWER8_LE - lxvw4x(40, 0, %[idx2be]) -#endif - - /* - * First subkey is a copy of the key itself. - */ -#if BR_POWER8_LE - vperm(4, 2, 2, 8) - stxvw4x(36, 0, %[sk]) -#else - stxvw4x(34, 0, %[sk]) -#endif - - /* - * Loop must run 10 times. - */ - li(%[cc], 10) - mtctr(%[cc]) - label(loop) - /* Increment subkey address */ - addi(%[sk], %[sk], 16) - - /* Compute SubWord(RotWord(temp)) xor Rcon (into v4, splat) */ - vrlw(4, 2, 1) - vsbox(4, 4) -#if BR_POWER8_LE - vxor(4, 4, 3) -#else - vsldoi(5, 3, 0, 3) - vxor(4, 4, 5) -#endif - vspltw(4, 4, 3) - - /* XOR words for next subkey */ - vsldoi(5, 0, 2, 12) - vxor(2, 2, 5) - vsldoi(5, 0, 2, 12) - vxor(2, 2, 5) - vsldoi(5, 0, 2, 12) - vxor(2, 2, 5) - vxor(2, 2, 4) - - /* Store next subkey */ -#if BR_POWER8_LE - vperm(4, 2, 2, 8) - stxvw4x(36, 0, %[sk]) -#else - stxvw4x(34, 0, %[sk]) -#endif - - /* Update Rcon */ - vadduwm(3, 3, 3) - vsrw(4, 3, 6) - vsubuwm(4, 0, 4) - vand(4, 4, 7) - vxor(3, 3, 4) - - bdnz(loop) - -: [sk] "+b" (sk), [cc] "+b" (cc) -: [key] "b" (key), [fmod] "b" (fmod) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "ctr", "memory" - ); -} - -static void -key_schedule_192(unsigned char *sk, const unsigned char *key) -{ - long cc; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - - /* - * We use the VSX instructions for loading and storing the - * key/subkeys, since they support unaligned accesses. The rest - * of the computation is VMX only. VMX register 0 is VSX - * register 32. - */ - asm volatile ( - - /* - * v0 = all-zero word - * v1 = constant -8 / +8, copied into four words - * v2, v3 = current subkey - * v5 = Rcon (x4 words) (already shifted on big-endian) - * v6 = constant 8, copied into four words - * v8 = constant for byteswapping words - * - * The left two words of v3 are ignored. - */ - vspltisw(0, 0) -#if BR_POWER8_LE - vspltisw(1, -8) -#else - vspltisw(1, 8) -#endif - li(%[cc], 8) - lxvw4x(34, 0, %[key]) - lxvw4x(35, %[cc], %[key]) - vsldoi(3, 3, 0, 8) - vspltisw(5, 1) -#if !BR_POWER8_LE - vsldoi(5, 5, 0, 3) -#endif - vspltisw(6, 8) -#if BR_POWER8_LE - lxvw4x(40, 0, %[idx2be]) -#endif - - /* - * Loop must run 8 times. Each iteration produces 256 - * bits of subkeys, with a 64-bit overlap. - */ - li(%[cc], 8) - mtctr(%[cc]) - li(%[cc], 16) - label(loop) - - /* - * Last 6 words in v2:v3l. Compute next 6 words into - * v3r:v4. - */ - vrlw(10, 3, 1) - vsbox(10, 10) - vxor(10, 10, 5) - vspltw(10, 10, 1) - vsldoi(11, 0, 10, 8) - - vsldoi(12, 0, 2, 12) - vxor(12, 2, 12) - vsldoi(13, 0, 12, 12) - vxor(12, 12, 13) - vsldoi(13, 0, 12, 12) - vxor(12, 12, 13) - - vspltw(13, 12, 3) - vxor(13, 13, 3) - vsldoi(14, 0, 3, 12) - vxor(13, 13, 14) - - vsldoi(4, 12, 13, 8) - vsldoi(14, 0, 3, 8) - vsldoi(3, 14, 12, 8) - - vxor(3, 3, 11) - vxor(4, 4, 10) - - /* - * Update Rcon. Since for a 192-bit key, we use only 8 - * such constants, we will not hit the field modulus, - * so a simple shift (addition) works well. - */ - vadduwm(5, 5, 5) - - /* - * Write out the two left 128-bit words - */ -#if BR_POWER8_LE - vperm(10, 2, 2, 8) - vperm(11, 3, 3, 8) - stxvw4x(42, 0, %[sk]) - stxvw4x(43, %[cc], %[sk]) -#else - stxvw4x(34, 0, %[sk]) - stxvw4x(35, %[cc], %[sk]) -#endif - addi(%[sk], %[sk], 24) - - /* - * Shift words for next iteration. - */ - vsldoi(2, 3, 4, 8) - vsldoi(3, 4, 0, 8) - - bdnz(loop) - - /* - * The loop wrote the first 50 subkey words, but we need - * to produce 52, so we must do one last write. - */ -#if BR_POWER8_LE - vperm(10, 2, 2, 8) - stxvw4x(42, 0, %[sk]) -#else - stxvw4x(34, 0, %[sk]) -#endif - -: [sk] "+b" (sk), [cc] "+b" (cc) -: [key] "b" (key) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", - "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory" - ); -} - -static void -key_schedule_256(unsigned char *sk, const unsigned char *key) -{ - long cc; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - - /* - * We use the VSX instructions for loading and storing the - * key/subkeys, since they support unaligned accesses. The rest - * of the computation is VMX only. VMX register 0 is VSX - * register 32. - */ - asm volatile ( - - /* - * v0 = all-zero word - * v1 = constant -8 / +8, copied into four words - * v2, v3 = current subkey - * v6 = Rcon (x4 words) (already shifted on big-endian) - * v7 = constant 8, copied into four words - * v8 = constant for byteswapping words - * - * The left two words of v3 are ignored. - */ - vspltisw(0, 0) -#if BR_POWER8_LE - vspltisw(1, -8) -#else - vspltisw(1, 8) -#endif - li(%[cc], 16) - lxvw4x(34, 0, %[key]) - lxvw4x(35, %[cc], %[key]) - vspltisw(6, 1) -#if !BR_POWER8_LE - vsldoi(6, 6, 0, 3) -#endif - vspltisw(7, 8) -#if BR_POWER8_LE - lxvw4x(40, 0, %[idx2be]) -#endif - - /* - * Loop must run 7 times. Each iteration produces two - * subkeys. - */ - li(%[cc], 7) - mtctr(%[cc]) - li(%[cc], 16) - label(loop) - - /* - * Current words are in v2:v3. Compute next word in v4. - */ - vrlw(10, 3, 1) - vsbox(10, 10) - vxor(10, 10, 6) - vspltw(10, 10, 3) - - vsldoi(4, 0, 2, 12) - vxor(4, 2, 4) - vsldoi(5, 0, 4, 12) - vxor(4, 4, 5) - vsldoi(5, 0, 4, 12) - vxor(4, 4, 5) - vxor(4, 4, 10) - - /* - * Then other word in v5. - */ - vsbox(10, 4) - vspltw(10, 10, 3) - - vsldoi(5, 0, 3, 12) - vxor(5, 3, 5) - vsldoi(11, 0, 5, 12) - vxor(5, 5, 11) - vsldoi(11, 0, 5, 12) - vxor(5, 5, 11) - vxor(5, 5, 10) - - /* - * Update Rcon. Since for a 256-bit key, we use only 7 - * such constants, we will not hit the field modulus, - * so a simple shift (addition) works well. - */ - vadduwm(6, 6, 6) - - /* - * Write out the two left 128-bit words - */ -#if BR_POWER8_LE - vperm(10, 2, 2, 8) - vperm(11, 3, 3, 8) - stxvw4x(42, 0, %[sk]) - stxvw4x(43, %[cc], %[sk]) -#else - stxvw4x(34, 0, %[sk]) - stxvw4x(35, %[cc], %[sk]) -#endif - addi(%[sk], %[sk], 32) - - /* - * Replace v2:v3 with v4:v5. - */ - vxor(2, 0, 4) - vxor(3, 0, 5) - - bdnz(loop) - - /* - * The loop wrote the first 14 subkeys, but we need 15, - * so we must do an extra write. - */ -#if BR_POWER8_LE - vperm(10, 2, 2, 8) - stxvw4x(42, 0, %[sk]) -#else - stxvw4x(34, 0, %[sk]) -#endif - -: [sk] "+b" (sk), [cc] "+b" (cc) -: [key] "b" (key) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", - "v8", "v9", "v10", "v11", "v12", "v13", "v14", "ctr", "memory" - ); -} - -/* see inner.h */ -int -br_aes_pwr8_supported(void) -{ - return 1; -} - -/* see inner.h */ -unsigned -br_aes_pwr8_keysched(unsigned char *sk, const void *key, size_t len) -{ - switch (len) { - case 16: - key_schedule_128(sk, key); - return 10; - case 24: - key_schedule_192(sk, key); - return 12; - default: - key_schedule_256(sk, key); - return 14; - } -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_pwr8_cbcdec.c b/src/tls/bearssl/aes_pwr8_cbcdec.c deleted file mode 100644 index 272665eaf..000000000 --- a/src/tls/bearssl/aes_pwr8_cbcdec.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -#if BR_POWER8 - -/* see bearssl_block.h */ -void -br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_pwr8_cbcdec_vtable; - ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); -} - -static void -cbcdec_128(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v10 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v24. - */ - lxvw4x(56, 0, %[iv]) -#if BR_POWER8_LE - vperm(24, 24, 24, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next ciphertext words in v16..v19. Also save them - * in v20..v23. - */ - lxvw4x(48, %[cc0], %[buf]) - lxvw4x(49, %[cc1], %[buf]) - lxvw4x(50, %[cc2], %[buf]) - lxvw4x(51, %[cc3], %[buf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - vand(20, 16, 16) - vand(21, 17, 17) - vand(22, 18, 18) - vand(23, 19, 19) - - /* - * Decrypt the blocks. - */ - vxor(16, 16, 10) - vxor(17, 17, 10) - vxor(18, 18, 10) - vxor(19, 19, 10) - vncipher(16, 16, 9) - vncipher(17, 17, 9) - vncipher(18, 18, 9) - vncipher(19, 19, 9) - vncipher(16, 16, 8) - vncipher(17, 17, 8) - vncipher(18, 18, 8) - vncipher(19, 19, 8) - vncipher(16, 16, 7) - vncipher(17, 17, 7) - vncipher(18, 18, 7) - vncipher(19, 19, 7) - vncipher(16, 16, 6) - vncipher(17, 17, 6) - vncipher(18, 18, 6) - vncipher(19, 19, 6) - vncipher(16, 16, 5) - vncipher(17, 17, 5) - vncipher(18, 18, 5) - vncipher(19, 19, 5) - vncipher(16, 16, 4) - vncipher(17, 17, 4) - vncipher(18, 18, 4) - vncipher(19, 19, 4) - vncipher(16, 16, 3) - vncipher(17, 17, 3) - vncipher(18, 18, 3) - vncipher(19, 19, 3) - vncipher(16, 16, 2) - vncipher(17, 17, 2) - vncipher(18, 18, 2) - vncipher(19, 19, 2) - vncipher(16, 16, 1) - vncipher(17, 17, 1) - vncipher(18, 18, 1) - vncipher(19, 19, 1) - vncipherlast(16, 16, 0) - vncipherlast(17, 17, 0) - vncipherlast(18, 18, 0) - vncipherlast(19, 19, 0) - - /* - * XOR decrypted blocks with IV / previous block. - */ - vxor(16, 16, 24) - vxor(17, 17, 20) - vxor(18, 18, 21) - vxor(19, 19, 22) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - /* - * Fourth encrypted block is IV for next run. - */ - vand(24, 23, 23) - - addi(%[buf], %[buf], 64) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -static void -cbcdec_192(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v12 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(43, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(44, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v24. - */ - lxvw4x(56, 0, %[iv]) -#if BR_POWER8_LE - vperm(24, 24, 24, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next ciphertext words in v16..v19. Also save them - * in v20..v23. - */ - lxvw4x(48, %[cc0], %[buf]) - lxvw4x(49, %[cc1], %[buf]) - lxvw4x(50, %[cc2], %[buf]) - lxvw4x(51, %[cc3], %[buf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - vand(20, 16, 16) - vand(21, 17, 17) - vand(22, 18, 18) - vand(23, 19, 19) - - /* - * Decrypt the blocks. - */ - vxor(16, 16, 12) - vxor(17, 17, 12) - vxor(18, 18, 12) - vxor(19, 19, 12) - vncipher(16, 16, 11) - vncipher(17, 17, 11) - vncipher(18, 18, 11) - vncipher(19, 19, 11) - vncipher(16, 16, 10) - vncipher(17, 17, 10) - vncipher(18, 18, 10) - vncipher(19, 19, 10) - vncipher(16, 16, 9) - vncipher(17, 17, 9) - vncipher(18, 18, 9) - vncipher(19, 19, 9) - vncipher(16, 16, 8) - vncipher(17, 17, 8) - vncipher(18, 18, 8) - vncipher(19, 19, 8) - vncipher(16, 16, 7) - vncipher(17, 17, 7) - vncipher(18, 18, 7) - vncipher(19, 19, 7) - vncipher(16, 16, 6) - vncipher(17, 17, 6) - vncipher(18, 18, 6) - vncipher(19, 19, 6) - vncipher(16, 16, 5) - vncipher(17, 17, 5) - vncipher(18, 18, 5) - vncipher(19, 19, 5) - vncipher(16, 16, 4) - vncipher(17, 17, 4) - vncipher(18, 18, 4) - vncipher(19, 19, 4) - vncipher(16, 16, 3) - vncipher(17, 17, 3) - vncipher(18, 18, 3) - vncipher(19, 19, 3) - vncipher(16, 16, 2) - vncipher(17, 17, 2) - vncipher(18, 18, 2) - vncipher(19, 19, 2) - vncipher(16, 16, 1) - vncipher(17, 17, 1) - vncipher(18, 18, 1) - vncipher(19, 19, 1) - vncipherlast(16, 16, 0) - vncipherlast(17, 17, 0) - vncipherlast(18, 18, 0) - vncipherlast(19, 19, 0) - - /* - * XOR decrypted blocks with IV / previous block. - */ - vxor(16, 16, 24) - vxor(17, 17, 20) - vxor(18, 18, 21) - vxor(19, 19, 22) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - /* - * Fourth encrypted block is IV for next run. - */ - vand(24, 23, 23) - - addi(%[buf], %[buf], 64) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -static void -cbcdec_256(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; - -#endif - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v14 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(43, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(44, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(45, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(46, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v24. - */ - lxvw4x(56, 0, %[iv]) -#if BR_POWER8_LE - vperm(24, 24, 24, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next ciphertext words in v16..v19. Also save them - * in v20..v23. - */ - lxvw4x(48, %[cc0], %[buf]) - lxvw4x(49, %[cc1], %[buf]) - lxvw4x(50, %[cc2], %[buf]) - lxvw4x(51, %[cc3], %[buf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - vand(20, 16, 16) - vand(21, 17, 17) - vand(22, 18, 18) - vand(23, 19, 19) - - /* - * Decrypt the blocks. - */ - vxor(16, 16, 14) - vxor(17, 17, 14) - vxor(18, 18, 14) - vxor(19, 19, 14) - vncipher(16, 16, 13) - vncipher(17, 17, 13) - vncipher(18, 18, 13) - vncipher(19, 19, 13) - vncipher(16, 16, 12) - vncipher(17, 17, 12) - vncipher(18, 18, 12) - vncipher(19, 19, 12) - vncipher(16, 16, 11) - vncipher(17, 17, 11) - vncipher(18, 18, 11) - vncipher(19, 19, 11) - vncipher(16, 16, 10) - vncipher(17, 17, 10) - vncipher(18, 18, 10) - vncipher(19, 19, 10) - vncipher(16, 16, 9) - vncipher(17, 17, 9) - vncipher(18, 18, 9) - vncipher(19, 19, 9) - vncipher(16, 16, 8) - vncipher(17, 17, 8) - vncipher(18, 18, 8) - vncipher(19, 19, 8) - vncipher(16, 16, 7) - vncipher(17, 17, 7) - vncipher(18, 18, 7) - vncipher(19, 19, 7) - vncipher(16, 16, 6) - vncipher(17, 17, 6) - vncipher(18, 18, 6) - vncipher(19, 19, 6) - vncipher(16, 16, 5) - vncipher(17, 17, 5) - vncipher(18, 18, 5) - vncipher(19, 19, 5) - vncipher(16, 16, 4) - vncipher(17, 17, 4) - vncipher(18, 18, 4) - vncipher(19, 19, 4) - vncipher(16, 16, 3) - vncipher(17, 17, 3) - vncipher(18, 18, 3) - vncipher(19, 19, 3) - vncipher(16, 16, 2) - vncipher(17, 17, 2) - vncipher(18, 18, 2) - vncipher(19, 19, 2) - vncipher(16, 16, 1) - vncipher(17, 17, 1) - vncipher(18, 18, 1) - vncipher(19, 19, 1) - vncipherlast(16, 16, 0) - vncipherlast(17, 17, 0) - vncipherlast(18, 18, 0) - vncipherlast(19, 19, 0) - - /* - * XOR decrypted blocks with IV / previous block. - */ - vxor(16, 16, 24) - vxor(17, 17, 20) - vxor(18, 18, 21) - vxor(19, 19, 22) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - /* - * Fourth encrypted block is IV for next run. - */ - vand(24, 23, 23) - - addi(%[buf], %[buf], 64) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (num_blocks >> 2) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char nextiv[16]; - unsigned char *buf; - - if (len == 0) { - return; - } - buf = data; - memcpy(nextiv, buf + len - 16, 16); - if (len >= 64) { - size_t num_blocks; - unsigned char tmp[16]; - - num_blocks = (len >> 4) & ~(size_t)3; - memcpy(tmp, buf + (num_blocks << 4) - 16, 16); - switch (ctx->num_rounds) { - case 10: - cbcdec_128(ctx->skey.skni, iv, buf, num_blocks); - break; - case 12: - cbcdec_192(ctx->skey.skni, iv, buf, num_blocks); - break; - default: - cbcdec_256(ctx->skey.skni, iv, buf, num_blocks); - break; - } - buf += num_blocks << 4; - len &= 63; - memcpy(iv, tmp, 16); - } - if (len > 0) { - unsigned char tmp[64]; - - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - switch (ctx->num_rounds) { - case 10: - cbcdec_128(ctx->skey.skni, iv, tmp, 4); - break; - case 12: - cbcdec_192(ctx->skey.skni, iv, tmp, 4); - break; - default: - cbcdec_256(ctx->skey.skni, iv, tmp, 4); - break; - } - memcpy(buf, tmp, len); - } - memcpy(iv, nextiv, 16); -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable = { - sizeof(br_aes_pwr8_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_pwr8_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_pwr8_cbcdec_run -}; - -/* see bearssl_block.h */ -const br_block_cbcdec_class * -br_aes_pwr8_cbcdec_get_vtable(void) -{ - return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcdec_vtable : NULL; -} - -#else - -/* see bearssl_block.h */ -const br_block_cbcdec_class * -br_aes_pwr8_cbcdec_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_pwr8_cbcenc.c b/src/tls/bearssl/aes_pwr8_cbcenc.c deleted file mode 100644 index 4f14ec6e4..000000000 --- a/src/tls/bearssl/aes_pwr8_cbcenc.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -#if BR_POWER8 - -/* see bearssl_block.h */ -void -br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_pwr8_cbcenc_vtable; - ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); -} - -static void -cbcenc_128(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t len) -{ - long cc; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - asm volatile ( - - /* - * Load subkeys into v0..v10 - */ - lxvw4x(32, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(33, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(34, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(35, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(36, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(37, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(38, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(39, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(40, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(41, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(42, %[cc], %[sk]) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v16. - */ - lxvw4x(48, 0, %[iv]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next plaintext word and XOR with current IV. - */ - lxvw4x(49, 0, %[buf]) -#if BR_POWER8_LE - vperm(17, 17, 17, 15) -#endif - vxor(16, 16, 17) - - /* - * Encrypt the block. - */ - vxor(16, 16, 0) - vcipher(16, 16, 1) - vcipher(16, 16, 2) - vcipher(16, 16, 3) - vcipher(16, 16, 4) - vcipher(16, 16, 5) - vcipher(16, 16, 6) - vcipher(16, 16, 7) - vcipher(16, 16, 8) - vcipher(16, 16, 9) - vcipherlast(16, 16, 10) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(17, 16, 16, 15) - stxvw4x(49, 0, %[buf]) -#else - stxvw4x(48, 0, %[buf]) -#endif - addi(%[buf], %[buf], 16) - - bdnz(loop) - -: [cc] "+b" (cc), [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "ctr", "memory" - ); -} - -static void -cbcenc_192(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t len) -{ - long cc; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - asm volatile ( - - /* - * Load subkeys into v0..v12 - */ - lxvw4x(32, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(33, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(34, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(35, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(36, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(37, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(38, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(39, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(40, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(41, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(42, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(43, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(44, %[cc], %[sk]) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v16. - */ - lxvw4x(48, 0, %[iv]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next plaintext word and XOR with current IV. - */ - lxvw4x(49, 0, %[buf]) -#if BR_POWER8_LE - vperm(17, 17, 17, 15) -#endif - vxor(16, 16, 17) - - /* - * Encrypt the block. - */ - vxor(16, 16, 0) - vcipher(16, 16, 1) - vcipher(16, 16, 2) - vcipher(16, 16, 3) - vcipher(16, 16, 4) - vcipher(16, 16, 5) - vcipher(16, 16, 6) - vcipher(16, 16, 7) - vcipher(16, 16, 8) - vcipher(16, 16, 9) - vcipher(16, 16, 10) - vcipher(16, 16, 11) - vcipherlast(16, 16, 12) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(17, 16, 16, 15) - stxvw4x(49, 0, %[buf]) -#else - stxvw4x(48, 0, %[buf]) -#endif - addi(%[buf], %[buf], 16) - - bdnz(loop) - -: [cc] "+b" (cc), [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "ctr", "memory" - ); -} - -static void -cbcenc_256(const unsigned char *sk, - const unsigned char *iv, unsigned char *buf, size_t len) -{ - long cc; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - cc = 0; - asm volatile ( - - /* - * Load subkeys into v0..v14 - */ - lxvw4x(32, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(33, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(34, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(35, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(36, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(37, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(38, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(39, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(40, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(41, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(42, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(43, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(44, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(45, %[cc], %[sk]) - addi(%[cc], %[cc], 16) - lxvw4x(46, %[cc], %[sk]) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * Load IV into v16. - */ - lxvw4x(48, 0, %[iv]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Load next plaintext word and XOR with current IV. - */ - lxvw4x(49, 0, %[buf]) -#if BR_POWER8_LE - vperm(17, 17, 17, 15) -#endif - vxor(16, 16, 17) - - /* - * Encrypt the block. - */ - vxor(16, 16, 0) - vcipher(16, 16, 1) - vcipher(16, 16, 2) - vcipher(16, 16, 3) - vcipher(16, 16, 4) - vcipher(16, 16, 5) - vcipher(16, 16, 6) - vcipher(16, 16, 7) - vcipher(16, 16, 8) - vcipher(16, 16, 9) - vcipher(16, 16, 10) - vcipher(16, 16, 11) - vcipher(16, 16, 12) - vcipher(16, 16, 13) - vcipherlast(16, 16, 14) - - /* - * Store back result (with byteswap) - */ -#if BR_POWER8_LE - vperm(17, 16, 16, 15) - stxvw4x(49, 0, %[buf]) -#else - stxvw4x(48, 0, %[buf]) -#endif - addi(%[buf], %[buf], 16) - - bdnz(loop) - -: [cc] "+b" (cc), [buf] "+b" (buf) -: [sk] "b" (sk), [iv] "b" (iv), [num_blocks] "b" (len >> 4) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "ctr", "memory" - ); -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - if (len > 0) { - switch (ctx->num_rounds) { - case 10: - cbcenc_128(ctx->skey.skni, iv, data, len); - break; - case 12: - cbcenc_192(ctx->skey.skni, iv, data, len); - break; - default: - cbcenc_256(ctx->skey.skni, iv, data, len); - break; - } - memcpy(iv, (unsigned char *)data + (len - 16), 16); - } -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable = { - sizeof(br_aes_pwr8_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_pwr8_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_pwr8_cbcenc_run -}; - -/* see bearssl_block.h */ -const br_block_cbcenc_class * -br_aes_pwr8_cbcenc_get_vtable(void) -{ - return br_aes_pwr8_supported() ? &br_aes_pwr8_cbcenc_vtable : NULL; -} - -#else - -/* see bearssl_block.h */ -const br_block_cbcenc_class * -br_aes_pwr8_cbcenc_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_pwr8_ctr.c b/src/tls/bearssl/aes_pwr8_ctr.c deleted file mode 100644 index 49babbf0a..000000000 --- a/src/tls/bearssl/aes_pwr8_ctr.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -#if BR_POWER8 - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_pwr8_ctr_vtable; - ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); -} - -static void -ctr_128(const unsigned char *sk, const unsigned char *ivbuf, - unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - static const uint32_t ctrinc[] = { - 0, 0, 0, 4 - }; - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v10 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * v28 = increment for IV counter. - */ - lxvw4x(60, 0, %[ctrinc]) - - /* - * Load IV into v16..v19 - */ - lxvw4x(48, %[cc0], %[ivbuf]) - lxvw4x(49, %[cc1], %[ivbuf]) - lxvw4x(50, %[cc2], %[ivbuf]) - lxvw4x(51, %[cc3], %[ivbuf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Compute next IV into v24..v27 - */ - vadduwm(24, 16, 28) - vadduwm(25, 17, 28) - vadduwm(26, 18, 28) - vadduwm(27, 19, 28) - - /* - * Load next data blocks. We do this early on but we - * won't need them until IV encryption is done. - */ - lxvw4x(52, %[cc0], %[buf]) - lxvw4x(53, %[cc1], %[buf]) - lxvw4x(54, %[cc2], %[buf]) - lxvw4x(55, %[cc3], %[buf]) - - /* - * Encrypt the current IV. - */ - vxor(16, 16, 0) - vxor(17, 17, 0) - vxor(18, 18, 0) - vxor(19, 19, 0) - vcipher(16, 16, 1) - vcipher(17, 17, 1) - vcipher(18, 18, 1) - vcipher(19, 19, 1) - vcipher(16, 16, 2) - vcipher(17, 17, 2) - vcipher(18, 18, 2) - vcipher(19, 19, 2) - vcipher(16, 16, 3) - vcipher(17, 17, 3) - vcipher(18, 18, 3) - vcipher(19, 19, 3) - vcipher(16, 16, 4) - vcipher(17, 17, 4) - vcipher(18, 18, 4) - vcipher(19, 19, 4) - vcipher(16, 16, 5) - vcipher(17, 17, 5) - vcipher(18, 18, 5) - vcipher(19, 19, 5) - vcipher(16, 16, 6) - vcipher(17, 17, 6) - vcipher(18, 18, 6) - vcipher(19, 19, 6) - vcipher(16, 16, 7) - vcipher(17, 17, 7) - vcipher(18, 18, 7) - vcipher(19, 19, 7) - vcipher(16, 16, 8) - vcipher(17, 17, 8) - vcipher(18, 18, 8) - vcipher(19, 19, 8) - vcipher(16, 16, 9) - vcipher(17, 17, 9) - vcipher(18, 18, 9) - vcipher(19, 19, 9) - vcipherlast(16, 16, 10) - vcipherlast(17, 17, 10) - vcipherlast(18, 18, 10) - vcipherlast(19, 19, 10) - -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - /* - * Load next plaintext word and XOR with encrypted IV. - */ - vxor(16, 20, 16) - vxor(17, 21, 17) - vxor(18, 22, 18) - vxor(19, 23, 19) - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - addi(%[buf], %[buf], 64) - - /* - * Update IV. - */ - vand(16, 24, 24) - vand(17, 25, 25) - vand(18, 26, 26) - vand(19, 27, 27) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), - [ctrinc] "b" (ctrinc) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -static void -ctr_192(const unsigned char *sk, const unsigned char *ivbuf, - unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - static const uint32_t ctrinc[] = { - 0, 0, 0, 4 - }; - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v12 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(43, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(44, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * v28 = increment for IV counter. - */ - lxvw4x(60, 0, %[ctrinc]) - - /* - * Load IV into v16..v19 - */ - lxvw4x(48, %[cc0], %[ivbuf]) - lxvw4x(49, %[cc1], %[ivbuf]) - lxvw4x(50, %[cc2], %[ivbuf]) - lxvw4x(51, %[cc3], %[ivbuf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Compute next IV into v24..v27 - */ - vadduwm(24, 16, 28) - vadduwm(25, 17, 28) - vadduwm(26, 18, 28) - vadduwm(27, 19, 28) - - /* - * Load next data blocks. We do this early on but we - * won't need them until IV encryption is done. - */ - lxvw4x(52, %[cc0], %[buf]) - lxvw4x(53, %[cc1], %[buf]) - lxvw4x(54, %[cc2], %[buf]) - lxvw4x(55, %[cc3], %[buf]) - - /* - * Encrypt the current IV. - */ - vxor(16, 16, 0) - vxor(17, 17, 0) - vxor(18, 18, 0) - vxor(19, 19, 0) - vcipher(16, 16, 1) - vcipher(17, 17, 1) - vcipher(18, 18, 1) - vcipher(19, 19, 1) - vcipher(16, 16, 2) - vcipher(17, 17, 2) - vcipher(18, 18, 2) - vcipher(19, 19, 2) - vcipher(16, 16, 3) - vcipher(17, 17, 3) - vcipher(18, 18, 3) - vcipher(19, 19, 3) - vcipher(16, 16, 4) - vcipher(17, 17, 4) - vcipher(18, 18, 4) - vcipher(19, 19, 4) - vcipher(16, 16, 5) - vcipher(17, 17, 5) - vcipher(18, 18, 5) - vcipher(19, 19, 5) - vcipher(16, 16, 6) - vcipher(17, 17, 6) - vcipher(18, 18, 6) - vcipher(19, 19, 6) - vcipher(16, 16, 7) - vcipher(17, 17, 7) - vcipher(18, 18, 7) - vcipher(19, 19, 7) - vcipher(16, 16, 8) - vcipher(17, 17, 8) - vcipher(18, 18, 8) - vcipher(19, 19, 8) - vcipher(16, 16, 9) - vcipher(17, 17, 9) - vcipher(18, 18, 9) - vcipher(19, 19, 9) - vcipher(16, 16, 10) - vcipher(17, 17, 10) - vcipher(18, 18, 10) - vcipher(19, 19, 10) - vcipher(16, 16, 11) - vcipher(17, 17, 11) - vcipher(18, 18, 11) - vcipher(19, 19, 11) - vcipherlast(16, 16, 12) - vcipherlast(17, 17, 12) - vcipherlast(18, 18, 12) - vcipherlast(19, 19, 12) - -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - /* - * Load next plaintext word and XOR with encrypted IV. - */ - vxor(16, 20, 16) - vxor(17, 21, 17) - vxor(18, 22, 18) - vxor(19, 23, 19) - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - addi(%[buf], %[buf], 64) - - /* - * Update IV. - */ - vand(16, 24, 24) - vand(17, 25, 25) - vand(18, 26, 26) - vand(19, 27, 27) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), - [ctrinc] "b" (ctrinc) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -static void -ctr_256(const unsigned char *sk, const unsigned char *ivbuf, - unsigned char *buf, size_t num_blocks) -{ - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - static const uint32_t ctrinc[] = { - 0, 0, 0, 4 - }; - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - - /* - * Load subkeys into v0..v14 - */ - lxvw4x(32, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(33, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(34, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(35, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(36, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(37, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(38, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(39, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(40, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(41, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(42, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(43, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(44, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(45, %[cc0], %[sk]) - addi(%[cc0], %[cc0], 16) - lxvw4x(46, %[cc0], %[sk]) - li(%[cc0], 0) - -#if BR_POWER8_LE - /* - * v15 = constant for byteswapping words - */ - lxvw4x(47, 0, %[idx2be]) -#endif - /* - * v28 = increment for IV counter. - */ - lxvw4x(60, 0, %[ctrinc]) - - /* - * Load IV into v16..v19 - */ - lxvw4x(48, %[cc0], %[ivbuf]) - lxvw4x(49, %[cc1], %[ivbuf]) - lxvw4x(50, %[cc2], %[ivbuf]) - lxvw4x(51, %[cc3], %[ivbuf]) -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - mtctr(%[num_blocks]) - label(loop) - /* - * Compute next IV into v24..v27 - */ - vadduwm(24, 16, 28) - vadduwm(25, 17, 28) - vadduwm(26, 18, 28) - vadduwm(27, 19, 28) - - /* - * Load next data blocks. We do this early on but we - * won't need them until IV encryption is done. - */ - lxvw4x(52, %[cc0], %[buf]) - lxvw4x(53, %[cc1], %[buf]) - lxvw4x(54, %[cc2], %[buf]) - lxvw4x(55, %[cc3], %[buf]) - - /* - * Encrypt the current IV. - */ - vxor(16, 16, 0) - vxor(17, 17, 0) - vxor(18, 18, 0) - vxor(19, 19, 0) - vcipher(16, 16, 1) - vcipher(17, 17, 1) - vcipher(18, 18, 1) - vcipher(19, 19, 1) - vcipher(16, 16, 2) - vcipher(17, 17, 2) - vcipher(18, 18, 2) - vcipher(19, 19, 2) - vcipher(16, 16, 3) - vcipher(17, 17, 3) - vcipher(18, 18, 3) - vcipher(19, 19, 3) - vcipher(16, 16, 4) - vcipher(17, 17, 4) - vcipher(18, 18, 4) - vcipher(19, 19, 4) - vcipher(16, 16, 5) - vcipher(17, 17, 5) - vcipher(18, 18, 5) - vcipher(19, 19, 5) - vcipher(16, 16, 6) - vcipher(17, 17, 6) - vcipher(18, 18, 6) - vcipher(19, 19, 6) - vcipher(16, 16, 7) - vcipher(17, 17, 7) - vcipher(18, 18, 7) - vcipher(19, 19, 7) - vcipher(16, 16, 8) - vcipher(17, 17, 8) - vcipher(18, 18, 8) - vcipher(19, 19, 8) - vcipher(16, 16, 9) - vcipher(17, 17, 9) - vcipher(18, 18, 9) - vcipher(19, 19, 9) - vcipher(16, 16, 10) - vcipher(17, 17, 10) - vcipher(18, 18, 10) - vcipher(19, 19, 10) - vcipher(16, 16, 11) - vcipher(17, 17, 11) - vcipher(18, 18, 11) - vcipher(19, 19, 11) - vcipher(16, 16, 12) - vcipher(17, 17, 12) - vcipher(18, 18, 12) - vcipher(19, 19, 12) - vcipher(16, 16, 13) - vcipher(17, 17, 13) - vcipher(18, 18, 13) - vcipher(19, 19, 13) - vcipherlast(16, 16, 14) - vcipherlast(17, 17, 14) - vcipherlast(18, 18, 14) - vcipherlast(19, 19, 14) - -#if BR_POWER8_LE - vperm(16, 16, 16, 15) - vperm(17, 17, 17, 15) - vperm(18, 18, 18, 15) - vperm(19, 19, 19, 15) -#endif - - /* - * Load next plaintext word and XOR with encrypted IV. - */ - vxor(16, 20, 16) - vxor(17, 21, 17) - vxor(18, 22, 18) - vxor(19, 23, 19) - stxvw4x(48, %[cc0], %[buf]) - stxvw4x(49, %[cc1], %[buf]) - stxvw4x(50, %[cc2], %[buf]) - stxvw4x(51, %[cc3], %[buf]) - - addi(%[buf], %[buf], 64) - - /* - * Update IV. - */ - vand(16, 24, 24) - vand(17, 25, 25) - vand(18, 26, 26) - vand(19, 27, 27) - - bdnz(loop) - -: [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3), - [buf] "+b" (buf) -: [sk] "b" (sk), [ivbuf] "b" (ivbuf), [num_blocks] "b" (num_blocks >> 2), - [ctrinc] "b" (ctrinc) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -/* see bearssl_block.h */ -uint32_t -br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - unsigned char ivbuf[64]; - - buf = data; - memcpy(ivbuf + 0, iv, 12); - memcpy(ivbuf + 16, iv, 12); - memcpy(ivbuf + 32, iv, 12); - memcpy(ivbuf + 48, iv, 12); - if (len >= 64) { - br_enc32be(ivbuf + 12, cc + 0); - br_enc32be(ivbuf + 28, cc + 1); - br_enc32be(ivbuf + 44, cc + 2); - br_enc32be(ivbuf + 60, cc + 3); - switch (ctx->num_rounds) { - case 10: - ctr_128(ctx->skey.skni, ivbuf, buf, - (len >> 4) & ~(size_t)3); - break; - case 12: - ctr_192(ctx->skey.skni, ivbuf, buf, - (len >> 4) & ~(size_t)3); - break; - default: - ctr_256(ctx->skey.skni, ivbuf, buf, - (len >> 4) & ~(size_t)3); - break; - } - cc += (len >> 4) & ~(size_t)3; - buf += len & ~(size_t)63; - len &= 63; - } - if (len > 0) { - unsigned char tmp[64]; - - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - br_enc32be(ivbuf + 12, cc + 0); - br_enc32be(ivbuf + 28, cc + 1); - br_enc32be(ivbuf + 44, cc + 2); - br_enc32be(ivbuf + 60, cc + 3); - switch (ctx->num_rounds) { - case 10: - ctr_128(ctx->skey.skni, ivbuf, tmp, 4); - break; - case 12: - ctr_192(ctx->skey.skni, ivbuf, tmp, 4); - break; - default: - ctr_256(ctx->skey.skni, ivbuf, tmp, 4); - break; - } - memcpy(buf, tmp, len); - cc += (len + 15) >> 4; - } - return cc; -} - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_pwr8_ctr_vtable = { - sizeof(br_aes_pwr8_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_pwr8_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_pwr8_ctr_run -}; - - -/* see bearssl_block.h */ -const br_block_ctr_class * -br_aes_pwr8_ctr_get_vtable(void) -{ - return br_aes_pwr8_supported() ? &br_aes_pwr8_ctr_vtable : NULL; -} - -#else - -/* see bearssl_block.h */ -const br_block_ctr_class * -br_aes_pwr8_ctr_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_pwr8_ctrcbc.c b/src/tls/bearssl/aes_pwr8_ctrcbc.c deleted file mode 100644 index 2afd9b461..000000000 --- a/src/tls/bearssl/aes_pwr8_ctrcbc.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -#if BR_POWER8 - -/* see bearssl_block.h */ -const br_block_ctrcbc_class * -br_aes_pwr8_ctrcbc_get_vtable(void) -{ - return br_aes_pwr8_supported() ? &br_aes_pwr8_ctrcbc_vtable : NULL; -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_pwr8_ctrcbc_vtable; - ctx->num_rounds = br_aes_pwr8_keysched(ctx->skey.skni, key, len); -} - -/* - * Register conventions for CTR + CBC-MAC: - * - * AES subkeys are in registers 0 to 10/12/14 (depending on keys size) - * Register v15 contains the byteswap index register (little-endian only) - * Register v16 contains the CTR counter value - * Register v17 contains the CBC-MAC current value - * Registers v18 to v27 are scratch - * Counter increment uses v28, v29 and v30 - * - * For CTR alone: - * - * AES subkeys are in registers 0 to 10/12/14 (depending on keys size) - * Register v15 contains the byteswap index register (little-endian only) - * Registers v16 to v19 contain the CTR counter values (four blocks) - * Registers v20 to v27 are scratch - * Counter increment uses v28, v29 and v30 - */ - -#define LOAD_SUBKEYS_128 \ - lxvw4x(32, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(33, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(34, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(35, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(36, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(37, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(38, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(39, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(40, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(41, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(42, %[cc], %[sk]) - -#define LOAD_SUBKEYS_192 \ - LOAD_SUBKEYS_128 \ - addi(%[cc], %[cc], 16) \ - lxvw4x(43, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(44, %[cc], %[sk]) - -#define LOAD_SUBKEYS_256 \ - LOAD_SUBKEYS_192 \ - addi(%[cc], %[cc], 16) \ - lxvw4x(45, %[cc], %[sk]) \ - addi(%[cc], %[cc], 16) \ - lxvw4x(46, %[cc], %[sk]) - -#define BLOCK_ENCRYPT_128(x) \ - vxor(x, x, 0) \ - vcipher(x, x, 1) \ - vcipher(x, x, 2) \ - vcipher(x, x, 3) \ - vcipher(x, x, 4) \ - vcipher(x, x, 5) \ - vcipher(x, x, 6) \ - vcipher(x, x, 7) \ - vcipher(x, x, 8) \ - vcipher(x, x, 9) \ - vcipherlast(x, x, 10) - -#define BLOCK_ENCRYPT_192(x) \ - vxor(x, x, 0) \ - vcipher(x, x, 1) \ - vcipher(x, x, 2) \ - vcipher(x, x, 3) \ - vcipher(x, x, 4) \ - vcipher(x, x, 5) \ - vcipher(x, x, 6) \ - vcipher(x, x, 7) \ - vcipher(x, x, 8) \ - vcipher(x, x, 9) \ - vcipher(x, x, 10) \ - vcipher(x, x, 11) \ - vcipherlast(x, x, 12) - -#define BLOCK_ENCRYPT_256(x) \ - vxor(x, x, 0) \ - vcipher(x, x, 1) \ - vcipher(x, x, 2) \ - vcipher(x, x, 3) \ - vcipher(x, x, 4) \ - vcipher(x, x, 5) \ - vcipher(x, x, 6) \ - vcipher(x, x, 7) \ - vcipher(x, x, 8) \ - vcipher(x, x, 9) \ - vcipher(x, x, 10) \ - vcipher(x, x, 11) \ - vcipher(x, x, 12) \ - vcipher(x, x, 13) \ - vcipherlast(x, x, 14) - -#define BLOCK_ENCRYPT_X2_128(x, y) \ - vxor(x, x, 0) \ - vxor(y, y, 0) \ - vcipher(x, x, 1) \ - vcipher(y, y, 1) \ - vcipher(x, x, 2) \ - vcipher(y, y, 2) \ - vcipher(x, x, 3) \ - vcipher(y, y, 3) \ - vcipher(x, x, 4) \ - vcipher(y, y, 4) \ - vcipher(x, x, 5) \ - vcipher(y, y, 5) \ - vcipher(x, x, 6) \ - vcipher(y, y, 6) \ - vcipher(x, x, 7) \ - vcipher(y, y, 7) \ - vcipher(x, x, 8) \ - vcipher(y, y, 8) \ - vcipher(x, x, 9) \ - vcipher(y, y, 9) \ - vcipherlast(x, x, 10) \ - vcipherlast(y, y, 10) - -#define BLOCK_ENCRYPT_X2_192(x, y) \ - vxor(x, x, 0) \ - vxor(y, y, 0) \ - vcipher(x, x, 1) \ - vcipher(y, y, 1) \ - vcipher(x, x, 2) \ - vcipher(y, y, 2) \ - vcipher(x, x, 3) \ - vcipher(y, y, 3) \ - vcipher(x, x, 4) \ - vcipher(y, y, 4) \ - vcipher(x, x, 5) \ - vcipher(y, y, 5) \ - vcipher(x, x, 6) \ - vcipher(y, y, 6) \ - vcipher(x, x, 7) \ - vcipher(y, y, 7) \ - vcipher(x, x, 8) \ - vcipher(y, y, 8) \ - vcipher(x, x, 9) \ - vcipher(y, y, 9) \ - vcipher(x, x, 10) \ - vcipher(y, y, 10) \ - vcipher(x, x, 11) \ - vcipher(y, y, 11) \ - vcipherlast(x, x, 12) \ - vcipherlast(y, y, 12) - -#define BLOCK_ENCRYPT_X2_256(x, y) \ - vxor(x, x, 0) \ - vxor(y, y, 0) \ - vcipher(x, x, 1) \ - vcipher(y, y, 1) \ - vcipher(x, x, 2) \ - vcipher(y, y, 2) \ - vcipher(x, x, 3) \ - vcipher(y, y, 3) \ - vcipher(x, x, 4) \ - vcipher(y, y, 4) \ - vcipher(x, x, 5) \ - vcipher(y, y, 5) \ - vcipher(x, x, 6) \ - vcipher(y, y, 6) \ - vcipher(x, x, 7) \ - vcipher(y, y, 7) \ - vcipher(x, x, 8) \ - vcipher(y, y, 8) \ - vcipher(x, x, 9) \ - vcipher(y, y, 9) \ - vcipher(x, x, 10) \ - vcipher(y, y, 10) \ - vcipher(x, x, 11) \ - vcipher(y, y, 11) \ - vcipher(x, x, 12) \ - vcipher(y, y, 12) \ - vcipher(x, x, 13) \ - vcipher(y, y, 13) \ - vcipherlast(x, x, 14) \ - vcipherlast(y, y, 14) - -#define BLOCK_ENCRYPT_X4_128(x0, x1, x2, x3) \ - vxor(x0, x0, 0) \ - vxor(x1, x1, 0) \ - vxor(x2, x2, 0) \ - vxor(x3, x3, 0) \ - vcipher(x0, x0, 1) \ - vcipher(x1, x1, 1) \ - vcipher(x2, x2, 1) \ - vcipher(x3, x3, 1) \ - vcipher(x0, x0, 2) \ - vcipher(x1, x1, 2) \ - vcipher(x2, x2, 2) \ - vcipher(x3, x3, 2) \ - vcipher(x0, x0, 3) \ - vcipher(x1, x1, 3) \ - vcipher(x2, x2, 3) \ - vcipher(x3, x3, 3) \ - vcipher(x0, x0, 4) \ - vcipher(x1, x1, 4) \ - vcipher(x2, x2, 4) \ - vcipher(x3, x3, 4) \ - vcipher(x0, x0, 5) \ - vcipher(x1, x1, 5) \ - vcipher(x2, x2, 5) \ - vcipher(x3, x3, 5) \ - vcipher(x0, x0, 6) \ - vcipher(x1, x1, 6) \ - vcipher(x2, x2, 6) \ - vcipher(x3, x3, 6) \ - vcipher(x0, x0, 7) \ - vcipher(x1, x1, 7) \ - vcipher(x2, x2, 7) \ - vcipher(x3, x3, 7) \ - vcipher(x0, x0, 8) \ - vcipher(x1, x1, 8) \ - vcipher(x2, x2, 8) \ - vcipher(x3, x3, 8) \ - vcipher(x0, x0, 9) \ - vcipher(x1, x1, 9) \ - vcipher(x2, x2, 9) \ - vcipher(x3, x3, 9) \ - vcipherlast(x0, x0, 10) \ - vcipherlast(x1, x1, 10) \ - vcipherlast(x2, x2, 10) \ - vcipherlast(x3, x3, 10) - -#define BLOCK_ENCRYPT_X4_192(x0, x1, x2, x3) \ - vxor(x0, x0, 0) \ - vxor(x1, x1, 0) \ - vxor(x2, x2, 0) \ - vxor(x3, x3, 0) \ - vcipher(x0, x0, 1) \ - vcipher(x1, x1, 1) \ - vcipher(x2, x2, 1) \ - vcipher(x3, x3, 1) \ - vcipher(x0, x0, 2) \ - vcipher(x1, x1, 2) \ - vcipher(x2, x2, 2) \ - vcipher(x3, x3, 2) \ - vcipher(x0, x0, 3) \ - vcipher(x1, x1, 3) \ - vcipher(x2, x2, 3) \ - vcipher(x3, x3, 3) \ - vcipher(x0, x0, 4) \ - vcipher(x1, x1, 4) \ - vcipher(x2, x2, 4) \ - vcipher(x3, x3, 4) \ - vcipher(x0, x0, 5) \ - vcipher(x1, x1, 5) \ - vcipher(x2, x2, 5) \ - vcipher(x3, x3, 5) \ - vcipher(x0, x0, 6) \ - vcipher(x1, x1, 6) \ - vcipher(x2, x2, 6) \ - vcipher(x3, x3, 6) \ - vcipher(x0, x0, 7) \ - vcipher(x1, x1, 7) \ - vcipher(x2, x2, 7) \ - vcipher(x3, x3, 7) \ - vcipher(x0, x0, 8) \ - vcipher(x1, x1, 8) \ - vcipher(x2, x2, 8) \ - vcipher(x3, x3, 8) \ - vcipher(x0, x0, 9) \ - vcipher(x1, x1, 9) \ - vcipher(x2, x2, 9) \ - vcipher(x3, x3, 9) \ - vcipher(x0, x0, 10) \ - vcipher(x1, x1, 10) \ - vcipher(x2, x2, 10) \ - vcipher(x3, x3, 10) \ - vcipher(x0, x0, 11) \ - vcipher(x1, x1, 11) \ - vcipher(x2, x2, 11) \ - vcipher(x3, x3, 11) \ - vcipherlast(x0, x0, 12) \ - vcipherlast(x1, x1, 12) \ - vcipherlast(x2, x2, 12) \ - vcipherlast(x3, x3, 12) - -#define BLOCK_ENCRYPT_X4_256(x0, x1, x2, x3) \ - vxor(x0, x0, 0) \ - vxor(x1, x1, 0) \ - vxor(x2, x2, 0) \ - vxor(x3, x3, 0) \ - vcipher(x0, x0, 1) \ - vcipher(x1, x1, 1) \ - vcipher(x2, x2, 1) \ - vcipher(x3, x3, 1) \ - vcipher(x0, x0, 2) \ - vcipher(x1, x1, 2) \ - vcipher(x2, x2, 2) \ - vcipher(x3, x3, 2) \ - vcipher(x0, x0, 3) \ - vcipher(x1, x1, 3) \ - vcipher(x2, x2, 3) \ - vcipher(x3, x3, 3) \ - vcipher(x0, x0, 4) \ - vcipher(x1, x1, 4) \ - vcipher(x2, x2, 4) \ - vcipher(x3, x3, 4) \ - vcipher(x0, x0, 5) \ - vcipher(x1, x1, 5) \ - vcipher(x2, x2, 5) \ - vcipher(x3, x3, 5) \ - vcipher(x0, x0, 6) \ - vcipher(x1, x1, 6) \ - vcipher(x2, x2, 6) \ - vcipher(x3, x3, 6) \ - vcipher(x0, x0, 7) \ - vcipher(x1, x1, 7) \ - vcipher(x2, x2, 7) \ - vcipher(x3, x3, 7) \ - vcipher(x0, x0, 8) \ - vcipher(x1, x1, 8) \ - vcipher(x2, x2, 8) \ - vcipher(x3, x3, 8) \ - vcipher(x0, x0, 9) \ - vcipher(x1, x1, 9) \ - vcipher(x2, x2, 9) \ - vcipher(x3, x3, 9) \ - vcipher(x0, x0, 10) \ - vcipher(x1, x1, 10) \ - vcipher(x2, x2, 10) \ - vcipher(x3, x3, 10) \ - vcipher(x0, x0, 11) \ - vcipher(x1, x1, 11) \ - vcipher(x2, x2, 11) \ - vcipher(x3, x3, 11) \ - vcipher(x0, x0, 12) \ - vcipher(x1, x1, 12) \ - vcipher(x2, x2, 12) \ - vcipher(x3, x3, 12) \ - vcipher(x0, x0, 13) \ - vcipher(x1, x1, 13) \ - vcipher(x2, x2, 13) \ - vcipher(x3, x3, 13) \ - vcipherlast(x0, x0, 14) \ - vcipherlast(x1, x1, 14) \ - vcipherlast(x2, x2, 14) \ - vcipherlast(x3, x3, 14) - -#if BR_POWER8_LE -static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C -}; - -#define BYTESWAP_INIT lxvw4x(47, 0, %[idx2be]) -#define BYTESWAP(x) vperm(x, x, x, 15) -#define BYTESWAPX(d, s) vperm(d, s, s, 15) -#define BYTESWAP_REG , [idx2be] "b" (idx2be) -#else -#define BYTESWAP_INIT -#define BYTESWAP(x) -#define BYTESWAPX(d, s) vand(d, s, s) -#define BYTESWAP_REG -#endif - -static const uint32_t ctrinc[] = { - 0, 0, 0, 1 -}; - -static const uint32_t ctrinc_x4[] = { - 0, 0, 0, 4 -}; - -#define INCR_128_INIT lxvw4x(60, 0, %[ctrinc]) -#define INCR_128_X4_INIT lxvw4x(60, 0, %[ctrinc_x4]) -#define INCR_128(d, s) \ - vaddcuw(29, s, 28) \ - vadduwm(d, s, 28) \ - vsldoi(30, 29, 29, 4) \ - vaddcuw(29, d, 30) \ - vadduwm(d, d, 30) \ - vsldoi(30, 29, 29, 4) \ - vaddcuw(29, d, 30) \ - vadduwm(d, d, 30) \ - vsldoi(30, 29, 29, 4) \ - vadduwm(d, d, 30) - -#define MKCTR(size) \ -static void \ -ctr_ ## size(const unsigned char *sk, \ - unsigned char *ctrbuf, unsigned char *buf, size_t num_blocks_x4) \ -{ \ - long cc, cc0, cc1, cc2, cc3; \ - \ - cc = 0; \ - cc0 = 0; \ - cc1 = 16; \ - cc2 = 32; \ - cc3 = 48; \ - asm volatile ( \ - \ - /* \ - * Load subkeys into v0..v10 \ - */ \ - LOAD_SUBKEYS_ ## size \ - li(%[cc], 0) \ - \ - BYTESWAP_INIT \ - INCR_128_X4_INIT \ - \ - /* \ - * Load current CTR counters into v16 to v19. \ - */ \ - lxvw4x(48, %[cc0], %[ctrbuf]) \ - lxvw4x(49, %[cc1], %[ctrbuf]) \ - lxvw4x(50, %[cc2], %[ctrbuf]) \ - lxvw4x(51, %[cc3], %[ctrbuf]) \ - BYTESWAP(16) \ - BYTESWAP(17) \ - BYTESWAP(18) \ - BYTESWAP(19) \ - \ - mtctr(%[num_blocks_x4]) \ - \ - label(loop) \ - /* \ - * Compute next counter values into v20..v23. \ - */ \ - INCR_128(20, 16) \ - INCR_128(21, 17) \ - INCR_128(22, 18) \ - INCR_128(23, 19) \ - \ - /* \ - * Encrypt counter values and XOR into next data blocks. \ - */ \ - lxvw4x(56, %[cc0], %[buf]) \ - lxvw4x(57, %[cc1], %[buf]) \ - lxvw4x(58, %[cc2], %[buf]) \ - lxvw4x(59, %[cc3], %[buf]) \ - BYTESWAP(24) \ - BYTESWAP(25) \ - BYTESWAP(26) \ - BYTESWAP(27) \ - BLOCK_ENCRYPT_X4_ ## size(16, 17, 18, 19) \ - vxor(16, 16, 24) \ - vxor(17, 17, 25) \ - vxor(18, 18, 26) \ - vxor(19, 19, 27) \ - BYTESWAP(16) \ - BYTESWAP(17) \ - BYTESWAP(18) \ - BYTESWAP(19) \ - stxvw4x(48, %[cc0], %[buf]) \ - stxvw4x(49, %[cc1], %[buf]) \ - stxvw4x(50, %[cc2], %[buf]) \ - stxvw4x(51, %[cc3], %[buf]) \ - \ - /* \ - * Update counters and data pointer. \ - */ \ - vand(16, 20, 20) \ - vand(17, 21, 21) \ - vand(18, 22, 22) \ - vand(19, 23, 23) \ - addi(%[buf], %[buf], 64) \ - \ - bdnz(loop) \ - \ - /* \ - * Write back new counter values. \ - */ \ - BYTESWAP(16) \ - BYTESWAP(17) \ - BYTESWAP(18) \ - BYTESWAP(19) \ - stxvw4x(48, %[cc0], %[ctrbuf]) \ - stxvw4x(49, %[cc1], %[ctrbuf]) \ - stxvw4x(50, %[cc2], %[ctrbuf]) \ - stxvw4x(51, %[cc3], %[ctrbuf]) \ - \ -: [cc] "+b" (cc), [buf] "+b" (buf), \ - [cc0] "+b" (cc0), [cc1] "+b" (cc1), [cc2] "+b" (cc2), [cc3] "+b" (cc3) \ -: [sk] "b" (sk), [ctrbuf] "b" (ctrbuf), \ - [num_blocks_x4] "b" (num_blocks_x4), [ctrinc_x4] "b" (ctrinc_x4) \ - BYTESWAP_REG \ -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ - "v30", "ctr", "memory" \ - ); \ -} - -MKCTR(128) -MKCTR(192) -MKCTR(256) - -#define MKCBCMAC(size) \ -static void \ -cbcmac_ ## size(const unsigned char *sk, \ - unsigned char *cbcmac, const unsigned char *buf, size_t num_blocks) \ -{ \ - long cc; \ - \ - cc = 0; \ - asm volatile ( \ - \ - /* \ - * Load subkeys into v0..v10 \ - */ \ - LOAD_SUBKEYS_ ## size \ - li(%[cc], 0) \ - \ - BYTESWAP_INIT \ - \ - /* \ - * Load current CBC-MAC value into v16. \ - */ \ - lxvw4x(48, %[cc], %[cbcmac]) \ - BYTESWAP(16) \ - \ - mtctr(%[num_blocks]) \ - \ - label(loop) \ - /* \ - * Load next block, XOR into current CBC-MAC value, \ - * and then encrypt it. \ - */ \ - lxvw4x(49, %[cc], %[buf]) \ - BYTESWAP(17) \ - vxor(16, 16, 17) \ - BLOCK_ENCRYPT_ ## size(16) \ - addi(%[buf], %[buf], 16) \ - \ - bdnz(loop) \ - \ - /* \ - * Write back new CBC-MAC value. \ - */ \ - BYTESWAP(16) \ - stxvw4x(48, %[cc], %[cbcmac]) \ - \ -: [cc] "+b" (cc), [buf] "+b" (buf) \ -: [sk] "b" (sk), [cbcmac] "b" (cbcmac), [num_blocks] "b" (num_blocks) \ - BYTESWAP_REG \ -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ - "v30", "ctr", "memory" \ - ); \ -} - -MKCBCMAC(128) -MKCBCMAC(192) -MKCBCMAC(256) - -#define MKENCRYPT(size) \ -static void \ -ctrcbc_ ## size ## _encrypt(const unsigned char *sk, \ - unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \ - size_t num_blocks) \ -{ \ - long cc; \ - \ - cc = 0; \ - asm volatile ( \ - \ - /* \ - * Load subkeys into v0..v10 \ - */ \ - LOAD_SUBKEYS_ ## size \ - li(%[cc], 0) \ - \ - BYTESWAP_INIT \ - INCR_128_INIT \ - \ - /* \ - * Load current CTR counter into v16, and current \ - * CBC-MAC IV into v17. \ - */ \ - lxvw4x(48, %[cc], %[ctr]) \ - lxvw4x(49, %[cc], %[cbcmac]) \ - BYTESWAP(16) \ - BYTESWAP(17) \ - \ - /* \ - * At each iteration, we do two parallel encryption: \ - * - new counter value for encryption of the next block; \ - * - CBC-MAC over the previous encrypted block. \ - * Thus, each plaintext block implies two AES instances, \ - * over two successive iterations. This requires a single \ - * counter encryption before the loop, and a single \ - * CBC-MAC encryption after the loop. \ - */ \ - \ - /* \ - * Encrypt first block (into v20). \ - */ \ - lxvw4x(52, %[cc], %[buf]) \ - BYTESWAP(20) \ - INCR_128(22, 16) \ - BLOCK_ENCRYPT_ ## size(16) \ - vxor(20, 20, 16) \ - BYTESWAPX(21, 20) \ - stxvw4x(53, %[cc], %[buf]) \ - vand(16, 22, 22) \ - addi(%[buf], %[buf], 16) \ - \ - /* \ - * Load loop counter; skip the loop if there is only \ - * one block in total (already handled by the boundary \ - * conditions). \ - */ \ - mtctr(%[num_blocks]) \ - bdz(fastexit) \ - \ - label(loop) \ - /* \ - * Upon loop entry: \ - * v16 counter value for next block \ - * v17 current CBC-MAC value \ - * v20 encrypted previous block \ - */ \ - vxor(17, 17, 20) \ - INCR_128(22, 16) \ - lxvw4x(52, %[cc], %[buf]) \ - BYTESWAP(20) \ - BLOCK_ENCRYPT_X2_ ## size(16, 17) \ - vxor(20, 20, 16) \ - BYTESWAPX(21, 20) \ - stxvw4x(53, %[cc], %[buf]) \ - addi(%[buf], %[buf], 16) \ - vand(16, 22, 22) \ - \ - bdnz(loop) \ - \ - label(fastexit) \ - vxor(17, 17, 20) \ - BLOCK_ENCRYPT_ ## size(17) \ - BYTESWAP(16) \ - BYTESWAP(17) \ - stxvw4x(48, %[cc], %[ctr]) \ - stxvw4x(49, %[cc], %[cbcmac]) \ - \ -: [cc] "+b" (cc), [buf] "+b" (buf) \ -: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \ - [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \ - BYTESWAP_REG \ -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ - "v30", "ctr", "memory" \ - ); \ -} - -MKENCRYPT(128) -MKENCRYPT(192) -MKENCRYPT(256) - -#define MKDECRYPT(size) \ -static void \ -ctrcbc_ ## size ## _decrypt(const unsigned char *sk, \ - unsigned char *ctr, unsigned char *cbcmac, unsigned char *buf, \ - size_t num_blocks) \ -{ \ - long cc; \ - \ - cc = 0; \ - asm volatile ( \ - \ - /* \ - * Load subkeys into v0..v10 \ - */ \ - LOAD_SUBKEYS_ ## size \ - li(%[cc], 0) \ - \ - BYTESWAP_INIT \ - INCR_128_INIT \ - \ - /* \ - * Load current CTR counter into v16, and current \ - * CBC-MAC IV into v17. \ - */ \ - lxvw4x(48, %[cc], %[ctr]) \ - lxvw4x(49, %[cc], %[cbcmac]) \ - BYTESWAP(16) \ - BYTESWAP(17) \ - \ - /* \ - * At each iteration, we do two parallel encryption: \ - * - new counter value for decryption of the next block; \ - * - CBC-MAC over the next encrypted block. \ - * Each iteration performs the two AES instances related \ - * to the current block; there is thus no need for some \ - * extra pre-loop and post-loop work as in encryption. \ - */ \ - \ - mtctr(%[num_blocks]) \ - \ - label(loop) \ - /* \ - * Upon loop entry: \ - * v16 counter value for next block \ - * v17 current CBC-MAC value \ - */ \ - lxvw4x(52, %[cc], %[buf]) \ - BYTESWAP(20) \ - vxor(17, 17, 20) \ - INCR_128(22, 16) \ - BLOCK_ENCRYPT_X2_ ## size(16, 17) \ - vxor(20, 20, 16) \ - BYTESWAPX(21, 20) \ - stxvw4x(53, %[cc], %[buf]) \ - addi(%[buf], %[buf], 16) \ - vand(16, 22, 22) \ - \ - bdnz(loop) \ - \ - /* \ - * Store back counter and CBC-MAC value. \ - */ \ - BYTESWAP(16) \ - BYTESWAP(17) \ - stxvw4x(48, %[cc], %[ctr]) \ - stxvw4x(49, %[cc], %[cbcmac]) \ - \ -: [cc] "+b" (cc), [buf] "+b" (buf) \ -: [sk] "b" (sk), [ctr] "b" (ctr), [cbcmac] "b" (cbcmac), \ - [num_blocks] "b" (num_blocks), [ctrinc] "b" (ctrinc) \ - BYTESWAP_REG \ -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", \ - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", \ - "v30", "ctr", "memory" \ - ); \ -} - -MKDECRYPT(128) -MKDECRYPT(192) -MKDECRYPT(256) - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - if (len == 0) { - return; - } - switch (ctx->num_rounds) { - case 10: - ctrcbc_128_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - case 12: - ctrcbc_192_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - default: - ctrcbc_256_encrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - } -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - if (len == 0) { - return; - } - switch (ctx->num_rounds) { - case 10: - ctrcbc_128_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - case 12: - ctrcbc_192_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - default: - ctrcbc_256_decrypt(ctx->skey.skni, ctr, cbcmac, data, len >> 4); - break; - } -} - -static inline void -incr_ctr(void *dst, const void *src) -{ - uint64_t hi, lo; - - hi = br_dec64be(src); - lo = br_dec64be((const unsigned char *)src + 8); - lo ++; - hi += ((lo | -lo) >> 63) ^ (uint64_t)1; - br_enc64be(dst, hi); - br_enc64be((unsigned char *)dst + 8, lo); -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len) -{ - unsigned char ctrbuf[64]; - - memcpy(ctrbuf, ctr, 16); - incr_ctr(ctrbuf + 16, ctrbuf); - incr_ctr(ctrbuf + 32, ctrbuf + 16); - incr_ctr(ctrbuf + 48, ctrbuf + 32); - if (len >= 64) { - switch (ctx->num_rounds) { - case 10: - ctr_128(ctx->skey.skni, ctrbuf, data, len >> 6); - break; - case 12: - ctr_192(ctx->skey.skni, ctrbuf, data, len >> 6); - break; - default: - ctr_256(ctx->skey.skni, ctrbuf, data, len >> 6); - break; - } - data = (unsigned char *)data + (len & ~(size_t)63); - len &= 63; - } - if (len > 0) { - unsigned char tmp[64]; - - if (len >= 32) { - if (len >= 48) { - memcpy(ctr, ctrbuf + 48, 16); - } else { - memcpy(ctr, ctrbuf + 32, 16); - } - } else { - if (len >= 16) { - memcpy(ctr, ctrbuf + 16, 16); - } - } - memcpy(tmp, data, len); - memset(tmp + len, 0, (sizeof tmp) - len); - switch (ctx->num_rounds) { - case 10: - ctr_128(ctx->skey.skni, ctrbuf, tmp, 1); - break; - case 12: - ctr_192(ctx->skey.skni, ctrbuf, tmp, 1); - break; - default: - ctr_256(ctx->skey.skni, ctrbuf, tmp, 1); - break; - } - memcpy(data, tmp, len); - } else { - memcpy(ctr, ctrbuf, 16); - } -} - -/* see bearssl_block.h */ -void -br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len) -{ - if (len > 0) { - switch (ctx->num_rounds) { - case 10: - cbcmac_128(ctx->skey.skni, cbcmac, data, len >> 4); - break; - case 12: - cbcmac_192(ctx->skey.skni, cbcmac, data, len >> 4); - break; - default: - cbcmac_256(ctx->skey.skni, cbcmac, data, len >> 4); - break; - } - } -} - -/* see bearssl_block.h */ -const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable = { - sizeof(br_aes_pwr8_ctrcbc_keys), - 16, - 4, - (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) - &br_aes_pwr8_ctrcbc_init, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_pwr8_ctrcbc_encrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_pwr8_ctrcbc_decrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, size_t)) - &br_aes_pwr8_ctrcbc_ctr, - (void (*)(const br_block_ctrcbc_class *const *, - void *, const void *, size_t)) - &br_aes_pwr8_ctrcbc_mac -}; - -#else - -/* see bearssl_block.h */ -const br_block_ctrcbc_class * -br_aes_pwr8_ctrcbc_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_cbcdec.c b/src/tls/bearssl/aes_small_cbcdec.c deleted file mode 100644 index 795841b04..000000000 --- a/src/tls/bearssl/aes_small_cbcdec.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_small_cbcdec_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - unsigned char tmp[16]; - int i; - - memcpy(tmp, buf, 16); - br_aes_small_decrypt(ctx->num_rounds, ctx->skey, buf); - for (i = 0; i < 16; i ++) { - buf[i] ^= ivbuf[i]; - } - memcpy(ivbuf, tmp, 16); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_small_cbcdec_vtable = { - sizeof(br_aes_small_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_small_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_small_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_cbcenc.c b/src/tls/bearssl/aes_small_cbcenc.c deleted file mode 100644 index bd38b32cf..000000000 --- a/src/tls/bearssl/aes_small_cbcenc.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_small_cbcenc_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - int i; - - for (i = 0; i < 16; i ++) { - buf[i] ^= ivbuf[i]; - } - br_aes_small_encrypt(ctx->num_rounds, ctx->skey, buf); - memcpy(ivbuf, buf, 16); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_small_cbcenc_vtable = { - sizeof(br_aes_small_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_small_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_small_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_ctr.c b/src/tls/bearssl/aes_small_ctr.c deleted file mode 100644 index 52531c2a5..000000000 --- a/src/tls/bearssl/aes_small_ctr.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_small_ctr_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -uint32_t -br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - - buf = data; - while (len > 0) { - unsigned char tmp[16]; - - memcpy(tmp, iv, 12); - br_enc32be(tmp + 12, cc ++); - br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp); - if (len <= 16) { - xorbuf(buf, tmp, len); - break; - } - xorbuf(buf, tmp, 16); - buf += 16; - len -= 16; - } - return cc; -} - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_small_ctr_vtable = { - sizeof(br_aes_small_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_small_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_small_ctr_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_ctrcbc.c b/src/tls/bearssl/aes_small_ctrcbc.c deleted file mode 100644 index 519f858a4..000000000 --- a/src/tls/bearssl/aes_small_ctrcbc.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_small_ctrcbc_vtable; - ctx->num_rounds = br_aes_keysched(ctx->skey, key, len); -} - -static void -xorbuf(void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - *d ++ ^= *s ++; - } -} - -/* see bearssl_block.h */ -void -br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len) -{ - unsigned char *buf, *bctr; - uint32_t cc0, cc1, cc2, cc3; - - buf = data; - bctr = ctr; - cc3 = br_dec32be(bctr + 0); - cc2 = br_dec32be(bctr + 4); - cc1 = br_dec32be(bctr + 8); - cc0 = br_dec32be(bctr + 12); - while (len > 0) { - unsigned char tmp[16]; - uint32_t carry; - - br_enc32be(tmp + 0, cc3); - br_enc32be(tmp + 4, cc2); - br_enc32be(tmp + 8, cc1); - br_enc32be(tmp + 12, cc0); - br_aes_small_encrypt(ctx->num_rounds, ctx->skey, tmp); - xorbuf(buf, tmp, 16); - buf += 16; - len -= 16; - cc0 ++; - carry = (~(cc0 | -cc0)) >> 31; - cc1 += carry; - carry &= (~(cc1 | -cc1)) >> 31; - cc2 += carry; - carry &= (~(cc2 | -cc2)) >> 31; - cc3 += carry; - } - br_enc32be(bctr + 0, cc3); - br_enc32be(bctr + 4, cc2); - br_enc32be(bctr + 8, cc1); - br_enc32be(bctr + 12, cc0); -} - -/* see bearssl_block.h */ -void -br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len) -{ - const unsigned char *buf; - - buf = data; - while (len > 0) { - xorbuf(cbcmac, buf, 16); - br_aes_small_encrypt(ctx->num_rounds, ctx->skey, cbcmac); - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -void -br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - br_aes_small_ctrcbc_ctr(ctx, ctr, data, len); - br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len); -} - -/* see bearssl_block.h */ -void -br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len) -{ - br_aes_small_ctrcbc_mac(ctx, cbcmac, data, len); - br_aes_small_ctrcbc_ctr(ctx, ctr, data, len); -} - -/* see bearssl_block.h */ -const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable = { - sizeof(br_aes_small_ctrcbc_keys), - 16, - 4, - (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) - &br_aes_small_ctrcbc_init, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_small_ctrcbc_encrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, void *, size_t)) - &br_aes_small_ctrcbc_decrypt, - (void (*)(const br_block_ctrcbc_class *const *, - void *, void *, size_t)) - &br_aes_small_ctrcbc_ctr, - (void (*)(const br_block_ctrcbc_class *const *, - void *, const void *, size_t)) - &br_aes_small_ctrcbc_mac -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_dec.c b/src/tls/bearssl/aes_small_dec.c deleted file mode 100644 index 0a6f0337e..000000000 --- a/src/tls/bearssl/aes_small_dec.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Inverse S-box. - */ -static const unsigned char iS[] = { - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, - 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, - 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, - 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, - 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, - 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, - 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, - 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, - 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, - 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, - 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, - 0x55, 0x21, 0x0C, 0x7D -}; - -static void -add_round_key(unsigned *state, const uint32_t *skeys) -{ - int i; - - for (i = 0; i < 16; i += 4) { - uint32_t k; - - k = *skeys ++; - state[i + 0] ^= (unsigned)(k >> 24); - state[i + 1] ^= (unsigned)(k >> 16) & 0xFF; - state[i + 2] ^= (unsigned)(k >> 8) & 0xFF; - state[i + 3] ^= (unsigned)k & 0xFF; - } -} - -static void -inv_sub_bytes(unsigned *state) -{ - int i; - - for (i = 0; i < 16; i ++) { - state[i] = iS[state[i]]; - } -} - -static void -inv_shift_rows(unsigned *state) -{ - unsigned tmp; - - tmp = state[13]; - state[13] = state[9]; - state[9] = state[5]; - state[5] = state[1]; - state[1] = tmp; - - tmp = state[2]; - state[2] = state[10]; - state[10] = tmp; - tmp = state[6]; - state[6] = state[14]; - state[14] = tmp; - - tmp = state[3]; - state[3] = state[7]; - state[7] = state[11]; - state[11] = state[15]; - state[15] = tmp; -} - -static inline unsigned -gf256red(unsigned x) -{ - unsigned y; - - y = x >> 8; - return (x ^ y ^ (y << 1) ^ (y << 3) ^ (y << 4)) & 0xFF; -} - -static void -inv_mix_columns(unsigned *state) -{ - int i; - - for (i = 0; i < 16; i += 4) { - unsigned s0, s1, s2, s3; - unsigned t0, t1, t2, t3; - - s0 = state[i + 0]; - s1 = state[i + 1]; - s2 = state[i + 2]; - s3 = state[i + 3]; - t0 = (s0 << 1) ^ (s0 << 2) ^ (s0 << 3) - ^ s1 ^ (s1 << 1) ^ (s1 << 3) - ^ s2 ^ (s2 << 2) ^ (s2 << 3) - ^ s3 ^ (s3 << 3); - t1 = s0 ^ (s0 << 3) - ^ (s1 << 1) ^ (s1 << 2) ^ (s1 << 3) - ^ s2 ^ (s2 << 1) ^ (s2 << 3) - ^ s3 ^ (s3 << 2) ^ (s3 << 3); - t2 = s0 ^ (s0 << 2) ^ (s0 << 3) - ^ s1 ^ (s1 << 3) - ^ (s2 << 1) ^ (s2 << 2) ^ (s2 << 3) - ^ s3 ^ (s3 << 1) ^ (s3 << 3); - t3 = s0 ^ (s0 << 1) ^ (s0 << 3) - ^ s1 ^ (s1 << 2) ^ (s1 << 3) - ^ s2 ^ (s2 << 3) - ^ (s3 << 1) ^ (s3 << 2) ^ (s3 << 3); - state[i + 0] = gf256red(t0); - state[i + 1] = gf256red(t1); - state[i + 2] = gf256red(t2); - state[i + 3] = gf256red(t3); - } -} - -/* see inner.h */ -void -br_aes_small_decrypt(unsigned num_rounds, const uint32_t *skey, void *data) -{ - unsigned char *buf; - unsigned state[16]; - unsigned u; - - buf = data; - for (u = 0; u < 16; u ++) { - state[u] = buf[u]; - } - add_round_key(state, skey + (num_rounds << 2)); - for (u = num_rounds - 1; u > 0; u --) { - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, skey + (u << 2)); - inv_mix_columns(state); - } - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, skey); - for (u = 0; u < 16; u ++) { - buf[u] = state[u]; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_small_enc.c b/src/tls/bearssl/aes_small_enc.c deleted file mode 100644 index a52a64a7e..000000000 --- a/src/tls/bearssl/aes_small_enc.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define S br_aes_S - -static void -add_round_key(unsigned *state, const uint32_t *skeys) -{ - int i; - - for (i = 0; i < 16; i += 4) { - uint32_t k; - - k = *skeys ++; - state[i + 0] ^= (unsigned)(k >> 24); - state[i + 1] ^= (unsigned)(k >> 16) & 0xFF; - state[i + 2] ^= (unsigned)(k >> 8) & 0xFF; - state[i + 3] ^= (unsigned)k & 0xFF; - } -} - -static void -sub_bytes(unsigned *state) -{ - int i; - - for (i = 0; i < 16; i ++) { - state[i] = S[state[i]]; - } -} - -static void -shift_rows(unsigned *state) -{ - unsigned tmp; - - tmp = state[1]; - state[1] = state[5]; - state[5] = state[9]; - state[9] = state[13]; - state[13] = tmp; - - tmp = state[2]; - state[2] = state[10]; - state[10] = tmp; - tmp = state[6]; - state[6] = state[14]; - state[14] = tmp; - - tmp = state[15]; - state[15] = state[11]; - state[11] = state[7]; - state[7] = state[3]; - state[3] = tmp; -} - -static void -mix_columns(unsigned *state) -{ - int i; - - for (i = 0; i < 16; i += 4) { - unsigned s0, s1, s2, s3; - unsigned t0, t1, t2, t3; - - s0 = state[i + 0]; - s1 = state[i + 1]; - s2 = state[i + 2]; - s3 = state[i + 3]; - t0 = (s0 << 1) ^ s1 ^ (s1 << 1) ^ s2 ^ s3; - t1 = s0 ^ (s1 << 1) ^ s2 ^ (s2 << 1) ^ s3; - t2 = s0 ^ s1 ^ (s2 << 1) ^ s3 ^ (s3 << 1); - t3 = s0 ^ (s0 << 1) ^ s1 ^ s2 ^ (s3 << 1); - state[i + 0] = t0 ^ ((unsigned)(-(int)(t0 >> 8)) & 0x11B); - state[i + 1] = t1 ^ ((unsigned)(-(int)(t1 >> 8)) & 0x11B); - state[i + 2] = t2 ^ ((unsigned)(-(int)(t2 >> 8)) & 0x11B); - state[i + 3] = t3 ^ ((unsigned)(-(int)(t3 >> 8)) & 0x11B); - } -} - -/* see inner.h */ -void -br_aes_small_encrypt(unsigned num_rounds, const uint32_t *skey, void *data) -{ - unsigned char *buf; - unsigned state[16]; - unsigned u; - - buf = data; - for (u = 0; u < 16; u ++) { - state[u] = buf[u]; - } - add_round_key(state, skey); - for (u = 1; u < num_rounds; u ++) { - sub_bytes(state); - shift_rows(state); - mix_columns(state); - add_round_key(state, skey + (u << 2)); - } - sub_bytes(state); - shift_rows(state); - add_round_key(state, skey + (num_rounds << 2)); - for (u = 0; u < 16; u ++) { - buf[u] = state[u]; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_x86ni.c b/src/tls/bearssl/aes_x86ni.c deleted file mode 100644 index ef1ea35a9..000000000 --- a/src/tls/bearssl/aes_x86ni.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * This code contains the AES key schedule implementation using the - * AES-NI opcodes. - */ - -#if BR_AES_X86NI - -#if BR_AES_X86NI_GCC -#if BR_AES_X86NI_GCC_OLD -#pragma GCC push_options -#pragma GCC target("sse2,sse4.1,aes,pclmul") -#endif -#include -#include -#if BR_AES_X86NI_GCC_OLD -#pragma GCC pop_options -#endif -#endif - -#if BR_AES_X86NI_MSC -#include -#endif - -/* see inner.h */ -int -br_aes_x86ni_supported(void) -{ - /* - * Bit mask for features in ECX: - * 19 SSE4.1 (used for _mm_insert_epi32(), for AES-CTR) - * 25 AES-NI - */ -#define MASK 0x02080000 - -#if BR_AES_X86NI_GCC - unsigned eax, ebx, ecx, edx; - - if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { - return (ecx & MASK) == MASK; - } else { - return 0; - } -#elif BR_AES_X86NI_MSC - int info[4]; - - __cpuid(info, 1); - return ((uint32_t)info[2] & MASK) == MASK; -#else - return 0; -#endif - -#undef MASK -} - -/* - * Per-function attributes appear unreliable on old GCC, so we use the - * pragma for all remaining functions in this file. - */ -#if BR_AES_X86NI_GCC_OLD -#pragma GCC target("sse2,sse4.1,aes,pclmul") -#endif - -BR_TARGET("sse2,aes") -static inline __m128i -expand_step128(__m128i k, __m128i k2) -{ - k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); - k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); - k = _mm_xor_si128(k, _mm_slli_si128(k, 4)); - k2 = _mm_shuffle_epi32(k2, 0xFF); - return _mm_xor_si128(k, k2); -} - -BR_TARGET("sse2,aes") -static inline void -expand_step192(__m128i *t1, __m128i *t2, __m128i *t3) -{ - __m128i t4; - - *t2 = _mm_shuffle_epi32(*t2, 0x55); - t4 = _mm_slli_si128(*t1, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - *t1 = _mm_xor_si128(*t1, *t2); - *t2 = _mm_shuffle_epi32(*t1, 0xFF); - t4 = _mm_slli_si128(*t3, 0x4); - *t3 = _mm_xor_si128(*t3, t4); - *t3 = _mm_xor_si128(*t3, *t2); -} - -BR_TARGET("sse2,aes") -static inline void -expand_step256_1(__m128i *t1, __m128i *t2) -{ - __m128i t4; - - *t2 = _mm_shuffle_epi32(*t2, 0xFF); - t4 = _mm_slli_si128(*t1, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t1 = _mm_xor_si128(*t1, t4); - *t1 = _mm_xor_si128(*t1, *t2); -} - -BR_TARGET("sse2,aes") -static inline void -expand_step256_2(__m128i *t1, __m128i *t3) -{ - __m128i t2, t4; - - t4 = _mm_aeskeygenassist_si128(*t1, 0x0); - t2 = _mm_shuffle_epi32(t4, 0xAA); - t4 = _mm_slli_si128(*t3, 0x4); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t3 = _mm_xor_si128(*t3, t4); - t4 = _mm_slli_si128(t4, 0x4); - *t3 = _mm_xor_si128(*t3, t4); - *t3 = _mm_xor_si128(*t3, t2); -} - -/* - * Perform key schedule for AES, encryption direction. Subkeys are written - * in sk[], and the number of rounds is returned. Key length MUST be 16, - * 24 or 32 bytes. - */ -BR_TARGET("sse2,aes") -static unsigned -x86ni_keysched(__m128i *sk, const void *key, size_t len) -{ - const unsigned char *kb; - -#define KEXP128(k, i, rcon) do { \ - k = expand_step128(k, _mm_aeskeygenassist_si128(k, rcon)); \ - sk[i] = k; \ - } while (0) - -#define KEXP192(i, rcon1, rcon2) do { \ - sk[(i) + 0] = t1; \ - sk[(i) + 1] = t3; \ - t2 = _mm_aeskeygenassist_si128(t3, rcon1); \ - expand_step192(&t1, &t2, &t3); \ - sk[(i) + 1] = _mm_castpd_si128(_mm_shuffle_pd( \ - _mm_castsi128_pd(sk[(i) + 1]), \ - _mm_castsi128_pd(t1), 0)); \ - sk[(i) + 2] = _mm_castpd_si128(_mm_shuffle_pd( \ - _mm_castsi128_pd(t1), \ - _mm_castsi128_pd(t3), 1)); \ - t2 = _mm_aeskeygenassist_si128(t3, rcon2); \ - expand_step192(&t1, &t2, &t3); \ - } while (0) - -#define KEXP256(i, rcon) do { \ - sk[(i) + 0] = t3; \ - t2 = _mm_aeskeygenassist_si128(t3, rcon); \ - expand_step256_1(&t1, &t2); \ - sk[(i) + 1] = t1; \ - expand_step256_2(&t1, &t3); \ - } while (0) - - kb = key; - switch (len) { - __m128i t1, t2, t3; - - case 16: - t1 = _mm_loadu_si128((const void *)kb); - sk[0] = t1; - KEXP128(t1, 1, 0x01); - KEXP128(t1, 2, 0x02); - KEXP128(t1, 3, 0x04); - KEXP128(t1, 4, 0x08); - KEXP128(t1, 5, 0x10); - KEXP128(t1, 6, 0x20); - KEXP128(t1, 7, 0x40); - KEXP128(t1, 8, 0x80); - KEXP128(t1, 9, 0x1B); - KEXP128(t1, 10, 0x36); - return 10; - - case 24: - t1 = _mm_loadu_si128((const void *)kb); - t3 = _mm_loadu_si128((const void *)(kb + 8)); - t3 = _mm_shuffle_epi32(t3, 0x4E); - KEXP192(0, 0x01, 0x02); - KEXP192(3, 0x04, 0x08); - KEXP192(6, 0x10, 0x20); - KEXP192(9, 0x40, 0x80); - sk[12] = t1; - return 12; - - case 32: - t1 = _mm_loadu_si128((const void *)kb); - t3 = _mm_loadu_si128((const void *)(kb + 16)); - sk[0] = t1; - KEXP256( 1, 0x01); - KEXP256( 3, 0x02); - KEXP256( 5, 0x04); - KEXP256( 7, 0x08); - KEXP256( 9, 0x10); - KEXP256(11, 0x20); - sk[13] = t3; - t2 = _mm_aeskeygenassist_si128(t3, 0x40); - expand_step256_1(&t1, &t2); - sk[14] = t1; - return 14; - - default: - return 0; - } - -#undef KEXP128 -#undef KEXP192 -#undef KEXP256 -} - -/* see inner.h */ -BR_TARGET("sse2,aes") -unsigned -br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len) -{ - __m128i sk[15]; - unsigned num_rounds; - - num_rounds = x86ni_keysched(sk, key, len); - memcpy(skni, sk, (num_rounds + 1) << 4); - return num_rounds; -} - -/* see inner.h */ -BR_TARGET("sse2,aes") -unsigned -br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len) -{ - __m128i sk[15]; - unsigned u, num_rounds; - - num_rounds = x86ni_keysched(sk, key, len); - _mm_storeu_si128((void *)skni, sk[num_rounds]); - for (u = 1; u < num_rounds; u ++) { - _mm_storeu_si128((void *)(skni + (u << 4)), - _mm_aesimc_si128(sk[num_rounds - u])); - } - _mm_storeu_si128((void *)(skni + (num_rounds << 4)), sk[0]); - return num_rounds; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_x86ni_cbcdec.c b/src/tls/bearssl/aes_x86ni_cbcdec.c deleted file mode 100644 index 7d7ec4ac9..000000000 --- a/src/tls/bearssl/aes_x86ni_cbcdec.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_ENABLE_INTRINSICS 1 -#include "inner.h" - -#if BR_AES_X86NI - -/* see bearssl_block.h */ -const br_block_cbcdec_class * -br_aes_x86ni_cbcdec_get_vtable(void) -{ - return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcdec_vtable : NULL; -} - -/* see bearssl_block.h */ -void -br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_x86ni_cbcdec_vtable; - ctx->num_rounds = br_aes_x86ni_keysched_dec(ctx->skey.skni, key, len); -} - -BR_TARGETS_X86_UP - -/* see bearssl_block.h */ -BR_TARGET("sse2,aes") -void -br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf; - unsigned num_rounds; - __m128i sk[15], ivx; - unsigned u; - - buf = data; - ivx = _mm_loadu_si128(iv); - num_rounds = ctx->num_rounds; - for (u = 0; u <= num_rounds; u ++) { - sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); - } - while (len > 0) { - __m128i x0, x1, x2, x3, e0, e1, e2, e3; - - x0 = _mm_loadu_si128((void *)(buf + 0)); - if (len >= 64) { - x1 = _mm_loadu_si128((void *)(buf + 16)); - x2 = _mm_loadu_si128((void *)(buf + 32)); - x3 = _mm_loadu_si128((void *)(buf + 48)); - } else { - x0 = _mm_loadu_si128((void *)(buf + 0)); - if (len >= 32) { - x1 = _mm_loadu_si128((void *)(buf + 16)); - if (len >= 48) { - x2 = _mm_loadu_si128( - (void *)(buf + 32)); - x3 = x2; - } else { - x2 = x0; - x3 = x1; - } - } else { - x1 = x0; - x2 = x0; - x3 = x0; - } - } - e0 = x0; - e1 = x1; - e2 = x2; - e3 = x3; - x0 = _mm_xor_si128(x0, sk[0]); - x1 = _mm_xor_si128(x1, sk[0]); - x2 = _mm_xor_si128(x2, sk[0]); - x3 = _mm_xor_si128(x3, sk[0]); - x0 = _mm_aesdec_si128(x0, sk[1]); - x1 = _mm_aesdec_si128(x1, sk[1]); - x2 = _mm_aesdec_si128(x2, sk[1]); - x3 = _mm_aesdec_si128(x3, sk[1]); - x0 = _mm_aesdec_si128(x0, sk[2]); - x1 = _mm_aesdec_si128(x1, sk[2]); - x2 = _mm_aesdec_si128(x2, sk[2]); - x3 = _mm_aesdec_si128(x3, sk[2]); - x0 = _mm_aesdec_si128(x0, sk[3]); - x1 = _mm_aesdec_si128(x1, sk[3]); - x2 = _mm_aesdec_si128(x2, sk[3]); - x3 = _mm_aesdec_si128(x3, sk[3]); - x0 = _mm_aesdec_si128(x0, sk[4]); - x1 = _mm_aesdec_si128(x1, sk[4]); - x2 = _mm_aesdec_si128(x2, sk[4]); - x3 = _mm_aesdec_si128(x3, sk[4]); - x0 = _mm_aesdec_si128(x0, sk[5]); - x1 = _mm_aesdec_si128(x1, sk[5]); - x2 = _mm_aesdec_si128(x2, sk[5]); - x3 = _mm_aesdec_si128(x3, sk[5]); - x0 = _mm_aesdec_si128(x0, sk[6]); - x1 = _mm_aesdec_si128(x1, sk[6]); - x2 = _mm_aesdec_si128(x2, sk[6]); - x3 = _mm_aesdec_si128(x3, sk[6]); - x0 = _mm_aesdec_si128(x0, sk[7]); - x1 = _mm_aesdec_si128(x1, sk[7]); - x2 = _mm_aesdec_si128(x2, sk[7]); - x3 = _mm_aesdec_si128(x3, sk[7]); - x0 = _mm_aesdec_si128(x0, sk[8]); - x1 = _mm_aesdec_si128(x1, sk[8]); - x2 = _mm_aesdec_si128(x2, sk[8]); - x3 = _mm_aesdec_si128(x3, sk[8]); - x0 = _mm_aesdec_si128(x0, sk[9]); - x1 = _mm_aesdec_si128(x1, sk[9]); - x2 = _mm_aesdec_si128(x2, sk[9]); - x3 = _mm_aesdec_si128(x3, sk[9]); - if (num_rounds == 10) { - x0 = _mm_aesdeclast_si128(x0, sk[10]); - x1 = _mm_aesdeclast_si128(x1, sk[10]); - x2 = _mm_aesdeclast_si128(x2, sk[10]); - x3 = _mm_aesdeclast_si128(x3, sk[10]); - } else if (num_rounds == 12) { - x0 = _mm_aesdec_si128(x0, sk[10]); - x1 = _mm_aesdec_si128(x1, sk[10]); - x2 = _mm_aesdec_si128(x2, sk[10]); - x3 = _mm_aesdec_si128(x3, sk[10]); - x0 = _mm_aesdec_si128(x0, sk[11]); - x1 = _mm_aesdec_si128(x1, sk[11]); - x2 = _mm_aesdec_si128(x2, sk[11]); - x3 = _mm_aesdec_si128(x3, sk[11]); - x0 = _mm_aesdeclast_si128(x0, sk[12]); - x1 = _mm_aesdeclast_si128(x1, sk[12]); - x2 = _mm_aesdeclast_si128(x2, sk[12]); - x3 = _mm_aesdeclast_si128(x3, sk[12]); - } else { - x0 = _mm_aesdec_si128(x0, sk[10]); - x1 = _mm_aesdec_si128(x1, sk[10]); - x2 = _mm_aesdec_si128(x2, sk[10]); - x3 = _mm_aesdec_si128(x3, sk[10]); - x0 = _mm_aesdec_si128(x0, sk[11]); - x1 = _mm_aesdec_si128(x1, sk[11]); - x2 = _mm_aesdec_si128(x2, sk[11]); - x3 = _mm_aesdec_si128(x3, sk[11]); - x0 = _mm_aesdec_si128(x0, sk[12]); - x1 = _mm_aesdec_si128(x1, sk[12]); - x2 = _mm_aesdec_si128(x2, sk[12]); - x3 = _mm_aesdec_si128(x3, sk[12]); - x0 = _mm_aesdec_si128(x0, sk[13]); - x1 = _mm_aesdec_si128(x1, sk[13]); - x2 = _mm_aesdec_si128(x2, sk[13]); - x3 = _mm_aesdec_si128(x3, sk[13]); - x0 = _mm_aesdeclast_si128(x0, sk[14]); - x1 = _mm_aesdeclast_si128(x1, sk[14]); - x2 = _mm_aesdeclast_si128(x2, sk[14]); - x3 = _mm_aesdeclast_si128(x3, sk[14]); - } - x0 = _mm_xor_si128(x0, ivx); - x1 = _mm_xor_si128(x1, e0); - x2 = _mm_xor_si128(x2, e1); - x3 = _mm_xor_si128(x3, e2); - ivx = e3; - _mm_storeu_si128((void *)(buf + 0), x0); - if (len >= 64) { - _mm_storeu_si128((void *)(buf + 16), x1); - _mm_storeu_si128((void *)(buf + 32), x2); - _mm_storeu_si128((void *)(buf + 48), x3); - buf += 64; - len -= 64; - } else { - if (len >= 32) { - _mm_storeu_si128((void *)(buf + 16), x1); - if (len >= 48) { - _mm_storeu_si128( - (void *)(buf + 32), x2); - } - } - break; - } - } - _mm_storeu_si128(iv, ivx); -} - -BR_TARGETS_X86_DOWN - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable = { - sizeof(br_aes_x86ni_cbcdec_keys), - 16, - 4, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_aes_x86ni_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_aes_x86ni_cbcdec_run -}; - -#else - -/* see bearssl_block.h */ -const br_block_cbcdec_class * -br_aes_x86ni_cbcdec_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_x86ni_cbcenc.c b/src/tls/bearssl/aes_x86ni_cbcenc.c deleted file mode 100644 index f2e14f2e8..000000000 --- a/src/tls/bearssl/aes_x86ni_cbcenc.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_AES_X86NI - -#if BR_AES_X86NI_GCC -#if BR_AES_X86NI_GCC_OLD -#pragma GCC target("sse2,sse4.1,aes,pclmul") -#endif -#include -#endif - -#if BR_AES_X86NI_MSC -#include -#endif - -/* see bearssl_block.h */ -void -br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_x86ni_cbcenc_vtable; - ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); -} - -/* see bearssl_block.h */ -BR_TARGET("sse2,aes") -void -br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf; - unsigned num_rounds; - __m128i sk[15], ivx; - unsigned u; - - buf = data; - ivx = _mm_loadu_si128(iv); - num_rounds = ctx->num_rounds; - for (u = 0; u <= num_rounds; u ++) { - sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); - } - while (len > 0) { - __m128i x; - - x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx); - x = _mm_xor_si128(x, sk[0]); - x = _mm_aesenc_si128(x, sk[1]); - x = _mm_aesenc_si128(x, sk[2]); - x = _mm_aesenc_si128(x, sk[3]); - x = _mm_aesenc_si128(x, sk[4]); - x = _mm_aesenc_si128(x, sk[5]); - x = _mm_aesenc_si128(x, sk[6]); - x = _mm_aesenc_si128(x, sk[7]); - x = _mm_aesenc_si128(x, sk[8]); - x = _mm_aesenc_si128(x, sk[9]); - if (num_rounds == 10) { - x = _mm_aesenclast_si128(x, sk[10]); - } else if (num_rounds == 12) { - x = _mm_aesenc_si128(x, sk[10]); - x = _mm_aesenc_si128(x, sk[11]); - x = _mm_aesenclast_si128(x, sk[12]); - } else { - x = _mm_aesenc_si128(x, sk[10]); - x = _mm_aesenc_si128(x, sk[11]); - x = _mm_aesenc_si128(x, sk[12]); - x = _mm_aesenc_si128(x, sk[13]); - x = _mm_aesenclast_si128(x, sk[14]); - } - ivx = x; - _mm_storeu_si128((void *)buf, x); - buf += 16; - len -= 16; - } - _mm_storeu_si128(iv, ivx); -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable = { - sizeof(br_aes_x86ni_cbcenc_keys), - 16, - 4, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_aes_x86ni_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_aes_x86ni_cbcenc_run -}; - -/* see bearssl_block.h */ -const br_block_cbcenc_class * -br_aes_x86ni_cbcenc_get_vtable(void) -{ - return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcenc_vtable : NULL; -} - -#else - -/* see bearssl_block.h */ -const br_block_cbcenc_class * -br_aes_x86ni_cbcenc_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aes_x86ni_ctr.c b/src/tls/bearssl/aes_x86ni_ctr.c deleted file mode 100644 index f26532743..000000000 --- a/src/tls/bearssl/aes_x86ni_ctr.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_ENABLE_INTRINSICS 1 -#include "inner.h" - -#if BR_AES_X86NI - -/* see bearssl_block.h */ -const br_block_ctr_class * -br_aes_x86ni_ctr_get_vtable(void) -{ - return br_aes_x86ni_supported() ? &br_aes_x86ni_ctr_vtable : NULL; -} - -/* see bearssl_block.h */ -void -br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_aes_x86ni_ctr_vtable; - ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len); -} - -BR_TARGETS_X86_UP - -/* see bearssl_block.h */ -BR_TARGET("sse2,sse4.1,aes") -uint32_t -br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - unsigned char ivbuf[16]; - unsigned num_rounds; - __m128i sk[15]; - __m128i ivx; - unsigned u; - - buf = data; - memcpy(ivbuf, iv, 12); - num_rounds = ctx->num_rounds; - for (u = 0; u <= num_rounds; u ++) { - sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4))); - } - ivx = _mm_loadu_si128((void *)ivbuf); - while (len > 0) { - __m128i x0, x1, x2, x3; - - x0 = _mm_insert_epi32(ivx, br_bswap32(cc + 0), 3); - x1 = _mm_insert_epi32(ivx, br_bswap32(cc + 1), 3); - x2 = _mm_insert_epi32(ivx, br_bswap32(cc + 2), 3); - x3 = _mm_insert_epi32(ivx, br_bswap32(cc + 3), 3); - x0 = _mm_xor_si128(x0, sk[0]); - x1 = _mm_xor_si128(x1, sk[0]); - x2 = _mm_xor_si128(x2, sk[0]); - x3 = _mm_xor_si128(x3, sk[0]); - x0 = _mm_aesenc_si128(x0, sk[1]); - x1 = _mm_aesenc_si128(x1, sk[1]); - x2 = _mm_aesenc_si128(x2, sk[1]); - x3 = _mm_aesenc_si128(x3, sk[1]); - x0 = _mm_aesenc_si128(x0, sk[2]); - x1 = _mm_aesenc_si128(x1, sk[2]); - x2 = _mm_aesenc_si128(x2, sk[2]); - x3 = _mm_aesenc_si128(x3, sk[2]); - x0 = _mm_aesenc_si128(x0, sk[3]); - x1 = _mm_aesenc_si128(x1, sk[3]); - x2 = _mm_aesenc_si128(x2, sk[3]); - x3 = _mm_aesenc_si128(x3, sk[3]); - x0 = _mm_aesenc_si128(x0, sk[4]); - x1 = _mm_aesenc_si128(x1, sk[4]); - x2 = _mm_aesenc_si128(x2, sk[4]); - x3 = _mm_aesenc_si128(x3, sk[4]); - x0 = _mm_aesenc_si128(x0, sk[5]); - x1 = _mm_aesenc_si128(x1, sk[5]); - x2 = _mm_aesenc_si128(x2, sk[5]); - x3 = _mm_aesenc_si128(x3, sk[5]); - x0 = _mm_aesenc_si128(x0, sk[6]); - x1 = _mm_aesenc_si128(x1, sk[6]); - x2 = _mm_aesenc_si128(x2, sk[6]); - x3 = _mm_aesenc_si128(x3, sk[6]); - x0 = _mm_aesenc_si128(x0, sk[7]); - x1 = _mm_aesenc_si128(x1, sk[7]); - x2 = _mm_aesenc_si128(x2, sk[7]); - x3 = _mm_aesenc_si128(x3, sk[7]); - x0 = _mm_aesenc_si128(x0, sk[8]); - x1 = _mm_aesenc_si128(x1, sk[8]); - x2 = _mm_aesenc_si128(x2, sk[8]); - x3 = _mm_aesenc_si128(x3, sk[8]); - x0 = _mm_aesenc_si128(x0, sk[9]); - x1 = _mm_aesenc_si128(x1, sk[9]); - x2 = _mm_aesenc_si128(x2, sk[9]); - x3 = _mm_aesenc_si128(x3, sk[9]); - if (num_rounds == 10) { - x0 = _mm_aesenclast_si128(x0, sk[10]); - x1 = _mm_aesenclast_si128(x1, sk[10]); - x2 = _mm_aesenclast_si128(x2, sk[10]); - x3 = _mm_aesenclast_si128(x3, sk[10]); - } else if (num_rounds == 12) { - x0 = _mm_aesenc_si128(x0, sk[10]); - x1 = _mm_aesenc_si128(x1, sk[10]); - x2 = _mm_aesenc_si128(x2, sk[10]); - x3 = _mm_aesenc_si128(x3, sk[10]); - x0 = _mm_aesenc_si128(x0, sk[11]); - x1 = _mm_aesenc_si128(x1, sk[11]); - x2 = _mm_aesenc_si128(x2, sk[11]); - x3 = _mm_aesenc_si128(x3, sk[11]); - x0 = _mm_aesenclast_si128(x0, sk[12]); - x1 = _mm_aesenclast_si128(x1, sk[12]); - x2 = _mm_aesenclast_si128(x2, sk[12]); - x3 = _mm_aesenclast_si128(x3, sk[12]); - } else { - x0 = _mm_aesenc_si128(x0, sk[10]); - x1 = _mm_aesenc_si128(x1, sk[10]); - x2 = _mm_aesenc_si128(x2, sk[10]); - x3 = _mm_aesenc_si128(x3, sk[10]); - x0 = _mm_aesenc_si128(x0, sk[11]); - x1 = _mm_aesenc_si128(x1, sk[11]); - x2 = _mm_aesenc_si128(x2, sk[11]); - x3 = _mm_aesenc_si128(x3, sk[11]); - x0 = _mm_aesenc_si128(x0, sk[12]); - x1 = _mm_aesenc_si128(x1, sk[12]); - x2 = _mm_aesenc_si128(x2, sk[12]); - x3 = _mm_aesenc_si128(x3, sk[12]); - x0 = _mm_aesenc_si128(x0, sk[13]); - x1 = _mm_aesenc_si128(x1, sk[13]); - x2 = _mm_aesenc_si128(x2, sk[13]); - x3 = _mm_aesenc_si128(x3, sk[13]); - x0 = _mm_aesenclast_si128(x0, sk[14]); - x1 = _mm_aesenclast_si128(x1, sk[14]); - x2 = _mm_aesenclast_si128(x2, sk[14]); - x3 = _mm_aesenclast_si128(x3, sk[14]); - } - if (len >= 64) { - x0 = _mm_xor_si128(x0, - _mm_loadu_si128((void *)(buf + 0))); - x1 = _mm_xor_si128(x1, - _mm_loadu_si128((void *)(buf + 16))); - x2 = _mm_xor_si128(x2, - _mm_loadu_si128((void *)(buf + 32))); - x3 = _mm_xor_si128(x3, - _mm_loadu_si128((void *)(buf + 48))); - _mm_storeu_si128((void *)(buf + 0), x0); - _mm_storeu_si128((void *)(buf + 16), x1); - _mm_storeu_si128((void *)(buf + 32), x2); - _mm_storeu_si128((void *)(buf + 48), x3); - buf += 64; - len -= 64; - cc += 4; - } else { - unsigned char tmp[64]; - - _mm_storeu_si128((void *)(tmp + 0), x0); - _mm_storeu_si128((void *)(tmp + 16), x1); - _mm_storeu_si128((void *)(tmp + 32), x2); - _mm_storeu_si128((void *)(tmp + 48), x3); - for (u = 0; u < len; u ++) { - buf[u] ^= tmp[u]; - } - cc += (uint32_t)len >> 4; - break; - } - } - return cc; -} - -BR_TARGETS_X86_DOWN - -/* see bearssl_block.h */ -const br_block_ctr_class br_aes_x86ni_ctr_vtable = { - sizeof(br_aes_x86ni_ctr_keys), - 16, - 4, - (void (*)(const br_block_ctr_class **, const void *, size_t)) - &br_aes_x86ni_ctr_init, - (uint32_t (*)(const br_block_ctr_class *const *, - const void *, uint32_t, void *, size_t)) - &br_aes_x86ni_ctr_run -}; - -#else - -/* see bearssl_block.h */ -const br_block_ctr_class * -br_aes_x86ni_ctr_get_vtable(void) -{ - return NULL; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/aesctr_drbg.c b/src/tls/bearssl/aesctr_drbg.c deleted file mode 100644 index 3d2db024c..000000000 --- a/src/tls/bearssl/aesctr_drbg.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rand.h */ -void -br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, - const br_block_ctr_class *aesctr, - const void *seed, size_t len) -{ - unsigned char tmp[16]; - - ctx->vtable = &br_aesctr_drbg_vtable; - memset(tmp, 0, sizeof tmp); - aesctr->init(&ctx->sk.vtable, tmp, 16); - ctx->cc = 0; - br_aesctr_drbg_update(ctx, seed, len); -} - -/* see bearssl_rand.h */ -void -br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len) -{ - unsigned char *buf; - unsigned char iv[12]; - - buf = out; - memset(iv, 0, sizeof iv); - while (len > 0) { - size_t clen; - - /* - * We generate data by blocks of at most 65280 bytes. This - * allows for unambiguously testing the counter overflow - * condition; also, it should work on 16-bit architectures - * (where 'size_t' is 16 bits only). - */ - clen = len; - if (clen > 65280) { - clen = 65280; - } - - /* - * We make sure that the counter won't exceed the configured - * limit. - */ - if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) { - clen = (32768 - ctx->cc) << 4; - if (clen > len) { - clen = len; - } - } - - /* - * Run CTR. - */ - memset(buf, 0, clen); - ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable, - iv, ctx->cc, buf, clen); - buf += clen; - len -= clen; - - /* - * Every 32768 blocks, we force a state update. - */ - if (ctx->cc >= 32768) { - br_aesctr_drbg_update(ctx, NULL, 0); - } - } -} - -/* see bearssl_rand.h */ -void -br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len) -{ - /* - * We use a Hirose construction on AES-256 to make a hash function. - * Function definition: - * - running state consists in two 16-byte blocks G and H - * - initial values of G and H are conventional - * - there is a fixed block-sized constant C - * - for next data block m: - * set AES key to H||m - * G' = E(G) xor G - * H' = E(G xor C) xor G xor C - * G <- G', H <- H' - * - once all blocks have been processed, output is H||G - * - * Constants: - * G_init = B6 B6 ... B6 - * H_init = A5 A5 ... A5 - * C = 01 00 ... 00 - * - * With this hash function h(), we compute the new state as - * follows: - * - produce a state-dependent value s as encryption of an - * all-one block with AES and the current key - * - compute the new key as the first 128 bits of h(s||seed) - * - * Original Hirose article: - * https://www.iacr.org/archive/fse2006/40470213/40470213.pdf - */ - - unsigned char s[16], iv[12]; - unsigned char G[16], H[16]; - int first; - - /* - * Use an all-one IV to get a fresh output block that depends on the - * current seed. - */ - memset(iv, 0xFF, sizeof iv); - memset(s, 0, 16); - ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16); - - /* - * Set G[] and H[] to conventional start values. - */ - memset(G, 0xB6, sizeof G); - memset(H, 0x5A, sizeof H); - - /* - * Process the concatenation of the current state and the seed - * with the custom hash function. - */ - first = 1; - for (;;) { - unsigned char tmp[32]; - unsigned char newG[16]; - - /* - * Assemble new key H||m into tmp[]. - */ - memcpy(tmp, H, 16); - if (first) { - memcpy(tmp + 16, s, 16); - first = 0; - } else { - size_t clen; - - if (len == 0) { - break; - } - clen = len < 16 ? len : 16; - memcpy(tmp + 16, seed, clen); - memset(tmp + 16 + clen, 0, 16 - clen); - seed = (const unsigned char *)seed + clen; - len -= clen; - } - ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32); - - /* - * Compute new G and H values. - */ - memcpy(iv, G, 12); - memcpy(newG, G, 16); - ctx->sk.vtable->run(&ctx->sk.vtable, iv, - br_dec32be(G + 12), newG, 16); - iv[0] ^= 0x01; - memcpy(H, G, 16); - H[0] ^= 0x01; - ctx->sk.vtable->run(&ctx->sk.vtable, iv, - br_dec32be(G + 12), H, 16); - memcpy(G, newG, 16); - } - - /* - * Output hash value is H||G. We truncate it to its first 128 bits, - * i.e. H; that's our new AES key. - */ - ctx->sk.vtable->init(&ctx->sk.vtable, H, 16); - ctx->cc = 0; -} - -/* see bearssl_rand.h */ -const br_prng_class br_aesctr_drbg_vtable = { - sizeof(br_aesctr_drbg_context), - (void (*)(const br_prng_class **, const void *, const void *, size_t)) - &br_aesctr_drbg_init, - (void (*)(const br_prng_class **, void *, size_t)) - &br_aesctr_drbg_generate, - (void (*)(const br_prng_class **, const void *, size_t)) - &br_aesctr_drbg_update -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/asn1enc.c b/src/tls/bearssl/asn1enc.c deleted file mode 100644 index c6a878113..000000000 --- a/src/tls/bearssl/asn1enc.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -br_asn1_uint -br_asn1_uint_prepare(const void *xdata, size_t xlen) -{ - const unsigned char *x; - br_asn1_uint t; - - x = xdata; - while (xlen > 0 && *x == 0) { - x ++; - xlen --; - } - t.data = x; - t.len = xlen; - t.asn1len = xlen; - if (xlen == 0 || x[0] >= 0x80) { - t.asn1len ++; - } - return t; -} - -/* see inner.h */ -size_t -br_asn1_encode_length(void *dest, size_t len) -{ - unsigned char *buf; - size_t z; - int i, j; - - buf = dest; - if (len < 0x80) { - if (buf != NULL) { - *buf = len; - } - return 1; - } - i = 0; - for (z = len; z != 0; z >>= 8) { - i ++; - } - if (buf != NULL) { - *buf ++ = 0x80 + i; - for (j = i - 1; j >= 0; j --) { - *buf ++ = len >> (j << 3); - } - } - return i + 1; -} - -/* see inner.h */ -size_t -br_asn1_encode_uint(void *dest, br_asn1_uint pp) -{ - unsigned char *buf; - size_t lenlen; - - if (dest == NULL) { - return 1 + br_asn1_encode_length(NULL, pp.asn1len) + pp.asn1len; - } - buf = dest; - *buf ++ = 0x02; - lenlen = br_asn1_encode_length(buf, pp.asn1len); - buf += lenlen; - *buf = 0x00; - memcpy(buf + pp.asn1len - pp.len, pp.data, pp.len); - return 1 + lenlen + pp.asn1len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/bearssl.h b/src/tls/bearssl/bearssl.h deleted file mode 100644 index 4f4797cf7..000000000 --- a/src/tls/bearssl/bearssl.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_H__ -#define BR_BEARSSL_H__ - -#include -#include - -/** \mainpage BearSSL API - * - * # API Layout - * - * The functions and structures defined by the BearSSL API are located - * in various header files: - * - * | Header file | Elements | - * | :-------------- | :------------------------------------------------ | - * | bearssl_hash.h | Hash functions | - * | bearssl_hmac.h | HMAC | - * | bearssl_kdf.h | Key Derivation Functions | - * | bearssl_rand.h | Pseudorandom byte generators | - * | bearssl_prf.h | PRF implementations (for SSL/TLS) | - * | bearssl_block.h | Symmetric encryption | - * | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) | - * | bearssl_rsa.h | RSA encryption and signatures | - * | bearssl_ec.h | Elliptic curves support (including ECDSA) | - * | bearssl_ssl.h | SSL/TLS engine interface | - * | bearssl_x509.h | X.509 certificate decoding and validation | - * | bearssl_pem.h | Base64/PEM decoding support functions | - * - * Applications using BearSSL are supposed to simply include `bearssl.h` - * as follows: - * - * #include - * - * The `bearssl.h` file itself includes all the other header files. It is - * possible to include specific header files, but it has no practical - * advantage for the application. The API is separated into separate - * header files only for documentation convenience. - * - * - * # Conventions - * - * ## MUST and SHALL - * - * In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology - * is used. Failure to meet requirements expressed with a "MUST" or - * "SHALL" implies undefined behaviour, which means that segmentation - * faults, buffer overflows, and other similar adverse events, may occur. - * - * In general, BearSSL is not very forgiving of programming errors, and - * does not include much failsafes or error reporting when the problem - * does not arise from external transient conditions, and can be fixed - * only in the application code. This is done so in order to make the - * total code footprint lighter. - * - * - * ## `NULL` values - * - * Function parameters with a pointer type shall not be `NULL` unless - * explicitly authorised by the documentation. As an exception, when - * the pointer aims at a sequence of bytes and is accompanied with - * a length parameter, and the length is zero (meaning that there is - * no byte at all to retrieve), then the pointer may be `NULL` even if - * not explicitly allowed. - * - * - * ## Memory Allocation - * - * BearSSL does not perform dynamic memory allocation. This implies that - * for any functionality that requires a non-transient state, the caller - * is responsible for allocating the relevant context structure. Such - * allocation can be done in any appropriate area, including static data - * segments, the heap, and the stack, provided that proper alignment is - * respected. The header files define these context structures - * (including size and contents), so the C compiler should handle - * alignment automatically. - * - * Since there is no dynamic resource allocation, there is also nothing to - * release. When the calling code is done with a BearSSL feature, it - * may simple release the context structures it allocated itself, with - * no "close function" to call. If the context structures were allocated - * on the stack (as local variables), then even that release operation is - * implicit. - * - * - * ## Structure Contents - * - * Except when explicitly indicated, structure contents are opaque: they - * are included in the header files so that calling code may know the - * structure sizes and alignment requirements, but callers SHALL NOT - * access individual fields directly. For fields that are supposed to - * be read from or written to, the API defines accessor functions (the - * simplest of these accessor functions are defined as `static inline` - * functions, and the C compiler will optimise them away). - * - * - * # API Usage - * - * BearSSL usage for running a SSL/TLS client or server is described - * on the [BearSSL Web site](https://www.bearssl.org/api1.html). The - * BearSSL source archive also comes with sample code. - */ - -#include "bearssl_hash.h" -#include "bearssl_hmac.h" -#include "bearssl_kdf.h" -#include "bearssl_rand.h" -#include "bearssl_prf.h" -#include "bearssl_block.h" -#include "bearssl_aead.h" -#include "bearssl_rsa.h" -#include "bearssl_ec.h" -#include "bearssl_ssl.h" -#include "bearssl_x509.h" -#include "bearssl_pem.h" - -/** \brief Type for a configuration option. - * - * A "configuration option" is a value that is selected when the BearSSL - * library itself is compiled. Most options are boolean; their value is - * then either 1 (option is enabled) or 0 (option is disabled). Some - * values have other integer values. Option names correspond to macro - * names. Some of the options can be explicitly set in the internal - * `"config.h"` file. - */ -typedef struct { - /** \brief Configurable option name. */ - const char *name; - /** \brief Configurable option value. */ - long value; -} br_config_option; - -/** \brief Get configuration report. - * - * This function returns compiled configuration options, each as a - * 'long' value. Names match internal macro names, in particular those - * that can be set in the `"config.h"` inner file. For boolean options, - * the numerical value is 1 if enabled, 0 if disabled. For maximum - * key sizes, values are expressed in bits. - * - * The returned array is terminated by an entry whose `name` is `NULL`. - * - * \return the configuration report. - */ -const br_config_option *br_get_config(void); - -#endif diff --git a/src/tls/bearssl/bearssl_aead.h b/src/tls/bearssl/bearssl_aead.h deleted file mode 100644 index 8e35a1fde..000000000 --- a/src/tls/bearssl/bearssl_aead.h +++ /dev/null @@ -1,1059 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_AEAD_H__ -#define BR_BEARSSL_AEAD_H__ - -#include -#include - -#include "bearssl_block.h" -#include "bearssl_hash.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_aead.h - * - * # Authenticated Encryption with Additional Data - * - * This file documents the API for AEAD encryption. - * - * - * ## Procedural API - * - * An AEAD algorithm processes messages and provides confidentiality - * (encryption) and checked integrity (MAC). It uses the following - * parameters: - * - * - A symmetric key. Exact size depends on the AEAD algorithm. - * - * - A nonce (IV). Size depends on the AEAD algorithm; for most - * algorithms, it is crucial for security that any given nonce - * value is never used twice for the same key and distinct - * messages. - * - * - Data to encrypt and protect. - * - * - Additional authenticated data, which is covered by the MAC but - * otherwise left untouched (i.e. not encrypted). - * - * The AEAD algorithm encrypts the data, and produces an authentication - * tag. It is assumed that the encrypted data, the tag, the additional - * authenticated data and the nonce are sent to the receiver; the - * additional data and the nonce may be implicit (e.g. using elements of - * the underlying transport protocol, such as record sequence numbers). - * The receiver will recompute the tag value and compare it with the one - * received; if they match, then the data is correct, and can be - * decrypted and used; otherwise, at least one of the elements was - * altered in transit, normally leading to wholesale rejection of the - * complete message. - * - * For each AEAD algorithm, identified by a symbolic name (hereafter - * denoted as "`xxx`"), the following functions are defined: - * - * - `br_xxx_init()` - * - * Initialise the AEAD algorithm, on a provided context structure. - * Exact parameters depend on the algorithm, and may include - * pointers to extra implementations and context structures. The - * secret key is provided at this point, either directly or - * indirectly. - * - * - `br_xxx_reset()` - * - * Start a new AEAD computation. The nonce value is provided as - * parameter to this function. - * - * - `br_xxx_aad_inject()` - * - * Inject some additional authenticated data. Additional data may - * be provided in several chunks of arbitrary length. - * - * - `br_xxx_flip()` - * - * This function MUST be called after injecting all additional - * authenticated data, and before beginning to encrypt the plaintext - * (or decrypt the ciphertext). - * - * - `br_xxx_run()` - * - * Process some plaintext (to encrypt) or ciphertext (to decrypt). - * Encryption/decryption is done in place. Data may be provided in - * several chunks of arbitrary length. - * - * - `br_xxx_get_tag()` - * - * Compute the authentication tag. All message data (encrypted or - * decrypted) must have been injected at that point. Also, this - * call may modify internal context elements, so it may be called - * only once for a given AEAD computation. - * - * - `br_xxx_check_tag()` - * - * An alternative to `br_xxx_get_tag()`, meant to be used by the - * receiver: the authentication tag is internally recomputed, and - * compared with the one provided as parameter. - * - * This API makes the following assumptions on the AEAD algorithm: - * - * - Encryption does not expand the size of the ciphertext; there is - * no padding. This is true of most modern AEAD modes such as GCM. - * - * - The additional authenticated data must be processed first, - * before the encrypted/decrypted data. - * - * - Nonce, plaintext and additional authenticated data all consist - * in an integral number of bytes. There is no provision to use - * elements whose length in bits is not a multiple of 8. - * - * Each AEAD algorithm has its own requirements and limits on the sizes - * of additional data and plaintext. This API does not provide any - * way to report invalid usage; it is up to the caller to ensure that - * the provided key, nonce, and data elements all fit the algorithm's - * requirements. - * - * - * ## Object-Oriented API - * - * Each context structure begins with a field (called `vtable`) that - * points to an instance of a structure that references the relevant - * functions through pointers. Each such structure contains the - * following: - * - * - `reset` - * - * Pointer to the reset function, that allows starting a new - * computation. - * - * - `aad_inject` - * - * Pointer to the additional authenticated data injection function. - * - * - `flip` - * - * Pointer to the function that transitions from additional data - * to main message data processing. - * - * - `get_tag` - * - * Pointer to the function that computes and returns the tag. - * - * - `check_tag` - * - * Pointer to the function that computes and verifies the tag against - * a received value. - * - * Note that there is no OOP method for context initialisation: the - * various AEAD algorithms have different requirements that would not - * map well to a single initialisation API. - * - * The OOP API is not provided for CCM, due to its specific requirements - * (length of plaintext must be known in advance). - */ - -/** - * \brief Class type of an AEAD algorithm. - */ -typedef struct br_aead_class_ br_aead_class; -struct br_aead_class_ { - - /** - * \brief Size (in bytes) of authentication tags created by - * this AEAD algorithm. - */ - size_t tag_size; - - /** - * \brief Reset an AEAD context. - * - * This function resets an already initialised AEAD context for - * a new computation run. Implementations and keys are - * conserved. This function can be called at any time; it - * cancels any ongoing AEAD computation that uses the provided - * context structure. - - * The provided IV is a _nonce_. Each AEAD algorithm has its - * own requirements on IV size and contents; for most of them, - * it is crucial to security that each nonce value is used - * only once for a given secret key. - * - * \param cc AEAD context structure. - * \param iv AEAD nonce to use. - * \param len AEAD nonce length (in bytes). - */ - void (*reset)(const br_aead_class **cc, const void *iv, size_t len); - - /** - * \brief Inject additional authenticated data. - * - * The provided data is injected into a running AEAD - * computation. Additional data must be injected _before_ the - * call to `flip()`. Additional data can be injected in several - * chunks of arbitrary length. - * - * \param cc AEAD context structure. - * \param data pointer to additional authenticated data. - * \param len length of additional authenticated data (in bytes). - */ - void (*aad_inject)(const br_aead_class **cc, - const void *data, size_t len); - - /** - * \brief Finish injection of additional authenticated data. - * - * This function MUST be called before beginning the actual - * encryption or decryption (with `run()`), even if no - * additional authenticated data was injected. No additional - * authenticated data may be injected after this function call. - * - * \param cc AEAD context structure. - */ - void (*flip)(const br_aead_class **cc); - - /** - * \brief Encrypt or decrypt some data. - * - * Data encryption or decryption can be done after `flip()` has - * been called on the context. If `encrypt` is non-zero, then - * the provided data shall be plaintext, and it is encrypted in - * place. Otherwise, the data shall be ciphertext, and it is - * decrypted in place. - * - * Data may be provided in several chunks of arbitrary length. - * - * \param cc AEAD context structure. - * \param encrypt non-zero for encryption, zero for decryption. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ - void (*run)(const br_aead_class **cc, int encrypt, - void *data, size_t len); - - /** - * \brief Compute authentication tag. - * - * Compute the AEAD authentication tag. The tag length depends - * on the AEAD algorithm; it is written in the provided `tag` - * buffer. This call terminates the AEAD run: no data may be - * processed with that AEAD context afterwards, until `reset()` - * is called to initiate a new AEAD run. - * - * The tag value must normally be sent along with the encrypted - * data. When decrypting, the tag value must be recomputed and - * compared with the received tag: if the two tag values differ, - * then either the tag or the encrypted data was altered in - * transit. As an alternative to this function, the - * `check_tag()` function may be used to compute and check the - * tag value. - * - * Tag length depends on the AEAD algorithm. - * - * \param cc AEAD context structure. - * \param tag destination buffer for the tag. - */ - void (*get_tag)(const br_aead_class **cc, void *tag); - - /** - * \brief Compute and check authentication tag. - * - * This function is an alternative to `get_tag()`, and is - * normally used on the receiving end (i.e. when decrypting - * messages). The tag value is recomputed and compared with the - * provided tag value. If they match, 1 is returned; on - * mismatch, 0 is returned. A returned value of 0 means that the - * data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * Tag length depends on the AEAD algorithm. - * - * \param cc AEAD context structure. - * \param tag tag value to compare with. - * \return 1 on success (exact match of tag value), 0 otherwise. - */ - uint32_t (*check_tag)(const br_aead_class **cc, const void *tag); - - /** - * \brief Compute authentication tag (with truncation). - * - * This function is similar to `get_tag()`, except that the tag - * length is provided. Some AEAD algorithms allow several tag - * lengths, usually by truncating the normal tag. Shorter tags - * mechanically increase success probability of forgeries. - * The range of allowed tag lengths depends on the algorithm. - * - * \param cc AEAD context structure. - * \param tag destination buffer for the tag. - * \param len tag length (in bytes). - */ - void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len); - - /** - * \brief Compute and check authentication tag (with truncation). - * - * This function is similar to `check_tag()` except that it - * works over an explicit tag length. See `get_tag()` for a - * discussion of explicit tag lengths; the range of allowed tag - * lengths depends on the algorithm. - * - * \param cc AEAD context structure. - * \param tag tag value to compare with. - * \param len tag length (in bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ - uint32_t (*check_tag_trunc)(const br_aead_class **cc, - const void *tag, size_t len); -}; - -/** - * \brief Context structure for GCM. - * - * GCM is an AEAD mode that combines a block cipher in CTR mode with a - * MAC based on GHASH, to provide authenticated encryption: - * - * - Any block cipher with 16-byte blocks can be used with GCM. - * - * - The nonce can have any length, from 0 up to 2^64-1 bits; however, - * 96-bit nonces (12 bytes) are recommended (nonces with a length - * distinct from 12 bytes are internally hashed, which risks reusing - * nonce value with a small but not always negligible probability). - * - * - Additional authenticated data may have length up to 2^64-1 bits. - * - * - Message length may range up to 2^39-256 bits at most. - * - * - The authentication tag has length 16 bytes. - * - * The GCM initialisation function receives as parameter an - * _initialised_ block cipher implementation context, with the secret - * key already set. A pointer to that context will be kept within the - * GCM context structure. It is up to the caller to allocate and - * initialise that block cipher context. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_aead_class *vtable; - -#ifndef BR_DOXYGEN_IGNORE - const br_block_ctr_class **bctx; - br_ghash gh; - unsigned char h[16]; - unsigned char j0_1[12]; - unsigned char buf[16]; - unsigned char y[16]; - uint32_t j0_2, jc; - uint64_t count_aad, count_ctr; -#endif -} br_gcm_context; - -/** - * \brief Initialize a GCM context. - * - * A block cipher implementation, with its initialised context structure, - * is provided. The block cipher MUST use 16-byte blocks in CTR mode, - * and its secret key MUST have been already set in the provided context. - * A GHASH implementation must also be provided. The parameters are linked - * in the GCM context. - * - * After this function has been called, the `br_gcm_reset()` function must - * be called, to provide the IV for GCM computation. - * - * \param ctx GCM context structure. - * \param bctx block cipher context (already initialised with secret key). - * \param gh GHASH implementation. - */ -void br_gcm_init(br_gcm_context *ctx, - const br_block_ctr_class **bctx, br_ghash gh); - -/** - * \brief Reset a GCM context. - * - * This function resets an already initialised GCM context for a new - * computation run. Implementations and keys are conserved. This function - * can be called at any time; it cancels any ongoing GCM computation that - * uses the provided context structure. - * - * The provided IV is a _nonce_. It is critical to GCM security that IV - * values are not repeated for the same encryption key. IV can have - * arbitrary length (up to 2^64-1 bits), but the "normal" length is - * 96 bits (12 bytes). - * - * \param ctx GCM context structure. - * \param iv GCM nonce to use. - * \param len GCM nonce length (in bytes). - */ -void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len); - -/** - * \brief Inject additional authenticated data into GCM. - * - * The provided data is injected into a running GCM computation. Additional - * data must be injected _before_ the call to `br_gcm_flip()`. - * Additional data can be injected in several chunks of arbitrary length; - * the maximum total size of additional authenticated data is 2^64-1 - * bits. - * - * \param ctx GCM context structure. - * \param data pointer to additional authenticated data. - * \param len length of additional authenticated data (in bytes). - */ -void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len); - -/** - * \brief Finish injection of additional authenticated data into GCM. - * - * This function MUST be called before beginning the actual encryption - * or decryption (with `br_gcm_run()`), even if no additional authenticated - * data was injected. No additional authenticated data may be injected - * after this function call. - * - * \param ctx GCM context structure. - */ -void br_gcm_flip(br_gcm_context *ctx); - -/** - * \brief Encrypt or decrypt some data with GCM. - * - * Data encryption or decryption can be done after `br_gcm_flip()` - * has been called on the context. If `encrypt` is non-zero, then the - * provided data shall be plaintext, and it is encrypted in place. - * Otherwise, the data shall be ciphertext, and it is decrypted in place. - * - * Data may be provided in several chunks of arbitrary length. The maximum - * total length for data is 2^39-256 bits, i.e. about 65 gigabytes. - * - * \param ctx GCM context structure. - * \param encrypt non-zero for encryption, zero for decryption. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len); - -/** - * \brief Compute GCM authentication tag. - * - * Compute the GCM authentication tag. The tag is a 16-byte value which - * is written in the provided `tag` buffer. This call terminates the - * GCM run: no data may be processed with that GCM context afterwards, - * until `br_gcm_reset()` is called to initiate a new GCM run. - * - * The tag value must normally be sent along with the encrypted data. - * When decrypting, the tag value must be recomputed and compared with - * the received tag: if the two tag values differ, then either the tag - * or the encrypted data was altered in transit. As an alternative to - * this function, the `br_gcm_check_tag()` function can be used to - * compute and check the tag value. - * - * \param ctx GCM context structure. - * \param tag destination buffer for the tag (16 bytes). - */ -void br_gcm_get_tag(br_gcm_context *ctx, void *tag); - -/** - * \brief Compute and check GCM authentication tag. - * - * This function is an alternative to `br_gcm_get_tag()`, normally used - * on the receiving end (i.e. when decrypting value). The tag value is - * recomputed and compared with the provided tag value. If they match, 1 - * is returned; on mismatch, 0 is returned. A returned value of 0 means - * that the data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * \param ctx GCM context structure. - * \param tag tag value to compare with (16 bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ -uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag); - -/** - * \brief Compute GCM authentication tag (with truncation). - * - * This function is similar to `br_gcm_get_tag()`, except that it allows - * the tag to be truncated to a smaller length. The intended tag length - * is provided as `len` (in bytes); it MUST be no more than 16, but - * it may be smaller. Note that decreasing tag length mechanically makes - * forgeries easier; NIST SP 800-38D specifies that the tag length shall - * lie between 12 and 16 bytes (inclusive), but may be truncated down to - * 4 or 8 bytes, for specific applications that can tolerate it. It must - * also be noted that successful forgeries leak information on the - * authentication key, making subsequent forgeries easier. Therefore, - * tag truncation, and in particular truncation to sizes lower than 12 - * bytes, shall be envisioned only with great care. - * - * The tag is written in the provided `tag` buffer. This call terminates - * the GCM run: no data may be processed with that GCM context - * afterwards, until `br_gcm_reset()` is called to initiate a new GCM - * run. - * - * The tag value must normally be sent along with the encrypted data. - * When decrypting, the tag value must be recomputed and compared with - * the received tag: if the two tag values differ, then either the tag - * or the encrypted data was altered in transit. As an alternative to - * this function, the `br_gcm_check_tag_trunc()` function can be used to - * compute and check the tag value. - * - * \param ctx GCM context structure. - * \param tag destination buffer for the tag. - * \param len tag length (16 bytes or less). - */ -void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len); - -/** - * \brief Compute and check GCM authentication tag (with truncation). - * - * This function is an alternative to `br_gcm_get_tag_trunc()`, normally used - * on the receiving end (i.e. when decrypting value). The tag value is - * recomputed and compared with the provided tag value. If they match, 1 - * is returned; on mismatch, 0 is returned. A returned value of 0 means - * that the data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * Tag length MUST be 16 bytes or less. The normal GCM tag length is 16 - * bytes. See `br_check_tag_trunc()` for some discussion on the potential - * perils of truncating authentication tags. - * - * \param ctx GCM context structure. - * \param tag tag value to compare with. - * \param len tag length (in bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ -uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx, - const void *tag, size_t len); - -/** - * \brief Class instance for GCM. - */ -extern const br_aead_class br_gcm_vtable; - -/** - * \brief Context structure for EAX. - * - * EAX is an AEAD mode that combines a block cipher in CTR mode with - * CBC-MAC using the same block cipher and the same key, to provide - * authenticated encryption: - * - * - Any block cipher with 16-byte blocks can be used with EAX - * (technically, other block sizes are defined as well, but this - * is not implemented by these functions; shorter blocks also - * imply numerous security issues). - * - * - The nonce can have any length, as long as nonce values are - * not reused (thus, if nonces are randomly selected, the nonce - * size should be such that reuse probability is negligible). - * - * - Additional authenticated data length is unlimited. - * - * - Message length is unlimited. - * - * - The authentication tag has length 16 bytes. - * - * The EAX initialisation function receives as parameter an - * _initialised_ block cipher implementation context, with the secret - * key already set. A pointer to that context will be kept within the - * EAX context structure. It is up to the caller to allocate and - * initialise that block cipher context. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_aead_class *vtable; - -#ifndef BR_DOXYGEN_IGNORE - const br_block_ctrcbc_class **bctx; - unsigned char L2[16]; - unsigned char L4[16]; - unsigned char nonce[16]; - unsigned char head[16]; - unsigned char ctr[16]; - unsigned char cbcmac[16]; - unsigned char buf[16]; - size_t ptr; -#endif -} br_eax_context; - -/** - * \brief EAX captured state. - * - * Some internal values computed by EAX may be captured at various - * points, and reused for another EAX run with the same secret key, - * for lower per-message overhead. Captured values do not depend on - * the nonce. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - unsigned char st[3][16]; -#endif -} br_eax_state; - -/** - * \brief Initialize an EAX context. - * - * A block cipher implementation, with its initialised context - * structure, is provided. The block cipher MUST use 16-byte blocks in - * CTR + CBC-MAC mode, and its secret key MUST have been already set in - * the provided context. The parameters are linked in the EAX context. - * - * After this function has been called, the `br_eax_reset()` function must - * be called, to provide the nonce for EAX computation. - * - * \param ctx EAX context structure. - * \param bctx block cipher context (already initialised with secret key). - */ -void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx); - -/** - * \brief Capture pre-AAD state. - * - * This function precomputes key-dependent data, and stores it in the - * provided `st` structure. This structure should then be used with - * `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()` - * and then used with `br_eax_reset_post_aad()`. - * - * The EAX context structure is unmodified by this call. - * - * \param ctx EAX context structure. - * \param st recipient for captured state. - */ -void br_eax_capture(const br_eax_context *ctx, br_eax_state *st); - -/** - * \brief Reset an EAX context. - * - * This function resets an already initialised EAX context for a new - * computation run. Implementations and keys are conserved. This function - * can be called at any time; it cancels any ongoing EAX computation that - * uses the provided context structure. - * - * It is critical to EAX security that nonce values are not repeated for - * the same encryption key. Nonces can have arbitrary length. If nonces - * are randomly generated, then a nonce length of at least 128 bits (16 - * bytes) is recommended, to make nonce reuse probability sufficiently - * low. - * - * \param ctx EAX context structure. - * \param nonce EAX nonce to use. - * \param len EAX nonce length (in bytes). - */ -void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len); - -/** - * \brief Reset an EAX context with a pre-AAD captured state. - * - * This function is an alternative to `br_eax_reset()`, that reuses a - * previously captured state structure for lower per-message overhead. - * The state should have been populated with `br_eax_capture_state()` - * but not updated with `br_eax_get_aad_mac()`. - * - * After this function is called, additional authenticated data MUST - * be injected. At least one byte of additional authenticated data - * MUST be provided with `br_eax_aad_inject()`; computation result will - * be incorrect if `br_eax_flip()` is called right away. - * - * After injection of the AAD and call to `br_eax_flip()`, at least - * one message byte must be provided. Empty messages are not supported - * with this reset mode. - * - * \param ctx EAX context structure. - * \param st pre-AAD captured state. - * \param nonce EAX nonce to use. - * \param len EAX nonce length (in bytes). - */ -void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, - const void *nonce, size_t len); - -/** - * \brief Reset an EAX context with a post-AAD captured state. - * - * This function is an alternative to `br_eax_reset()`, that reuses a - * previously captured state structure for lower per-message overhead. - * The state should have been populated with `br_eax_capture_state()` - * and then updated with `br_eax_get_aad_mac()`. - * - * After this function is called, message data MUST be injected. The - * `br_eax_flip()` function MUST NOT be called. At least one byte of - * message data MUST be provided with `br_eax_run()`; empty messages - * are not supported with this reset mode. - * - * \param ctx EAX context structure. - * \param st post-AAD captured state. - * \param nonce EAX nonce to use. - * \param len EAX nonce length (in bytes). - */ -void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, - const void *nonce, size_t len); - -/** - * \brief Inject additional authenticated data into EAX. - * - * The provided data is injected into a running EAX computation. Additional - * data must be injected _before_ the call to `br_eax_flip()`. - * Additional data can be injected in several chunks of arbitrary length; - * the total amount of additional authenticated data is unlimited. - * - * \param ctx EAX context structure. - * \param data pointer to additional authenticated data. - * \param len length of additional authenticated data (in bytes). - */ -void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len); - -/** - * \brief Finish injection of additional authenticated data into EAX. - * - * This function MUST be called before beginning the actual encryption - * or decryption (with `br_eax_run()`), even if no additional authenticated - * data was injected. No additional authenticated data may be injected - * after this function call. - * - * \param ctx EAX context structure. - */ -void br_eax_flip(br_eax_context *ctx); - -/** - * \brief Obtain a copy of the MAC on additional authenticated data. - * - * This function may be called only after `br_eax_flip()`; it copies the - * AAD-specific MAC value into the provided state. The MAC value depends - * on the secret key and the additional data itself, but not on the - * nonce. The updated state `st` is meant to be used as parameter for a - * further `br_eax_reset_post_aad()` call. - * - * \param ctx EAX context structure. - * \param st captured state to update. - */ -static inline void -br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st) -{ - memcpy(st->st[1], ctx->head, sizeof ctx->head); -} - -/** - * \brief Encrypt or decrypt some data with EAX. - * - * Data encryption or decryption can be done after `br_eax_flip()` - * has been called on the context. If `encrypt` is non-zero, then the - * provided data shall be plaintext, and it is encrypted in place. - * Otherwise, the data shall be ciphertext, and it is decrypted in place. - * - * Data may be provided in several chunks of arbitrary length. - * - * \param ctx EAX context structure. - * \param encrypt non-zero for encryption, zero for decryption. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len); - -/** - * \brief Compute EAX authentication tag. - * - * Compute the EAX authentication tag. The tag is a 16-byte value which - * is written in the provided `tag` buffer. This call terminates the - * EAX run: no data may be processed with that EAX context afterwards, - * until `br_eax_reset()` is called to initiate a new EAX run. - * - * The tag value must normally be sent along with the encrypted data. - * When decrypting, the tag value must be recomputed and compared with - * the received tag: if the two tag values differ, then either the tag - * or the encrypted data was altered in transit. As an alternative to - * this function, the `br_eax_check_tag()` function can be used to - * compute and check the tag value. - * - * \param ctx EAX context structure. - * \param tag destination buffer for the tag (16 bytes). - */ -void br_eax_get_tag(br_eax_context *ctx, void *tag); - -/** - * \brief Compute and check EAX authentication tag. - * - * This function is an alternative to `br_eax_get_tag()`, normally used - * on the receiving end (i.e. when decrypting value). The tag value is - * recomputed and compared with the provided tag value. If they match, 1 - * is returned; on mismatch, 0 is returned. A returned value of 0 means - * that the data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * \param ctx EAX context structure. - * \param tag tag value to compare with (16 bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ -uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag); - -/** - * \brief Compute EAX authentication tag (with truncation). - * - * This function is similar to `br_eax_get_tag()`, except that it allows - * the tag to be truncated to a smaller length. The intended tag length - * is provided as `len` (in bytes); it MUST be no more than 16, but - * it may be smaller. Note that decreasing tag length mechanically makes - * forgeries easier; NIST SP 800-38D specifies that the tag length shall - * lie between 12 and 16 bytes (inclusive), but may be truncated down to - * 4 or 8 bytes, for specific applications that can tolerate it. It must - * also be noted that successful forgeries leak information on the - * authentication key, making subsequent forgeries easier. Therefore, - * tag truncation, and in particular truncation to sizes lower than 12 - * bytes, shall be envisioned only with great care. - * - * The tag is written in the provided `tag` buffer. This call terminates - * the EAX run: no data may be processed with that EAX context - * afterwards, until `br_eax_reset()` is called to initiate a new EAX - * run. - * - * The tag value must normally be sent along with the encrypted data. - * When decrypting, the tag value must be recomputed and compared with - * the received tag: if the two tag values differ, then either the tag - * or the encrypted data was altered in transit. As an alternative to - * this function, the `br_eax_check_tag_trunc()` function can be used to - * compute and check the tag value. - * - * \param ctx EAX context structure. - * \param tag destination buffer for the tag. - * \param len tag length (16 bytes or less). - */ -void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len); - -/** - * \brief Compute and check EAX authentication tag (with truncation). - * - * This function is an alternative to `br_eax_get_tag_trunc()`, normally used - * on the receiving end (i.e. when decrypting value). The tag value is - * recomputed and compared with the provided tag value. If they match, 1 - * is returned; on mismatch, 0 is returned. A returned value of 0 means - * that the data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * Tag length MUST be 16 bytes or less. The normal EAX tag length is 16 - * bytes. See `br_check_tag_trunc()` for some discussion on the potential - * perils of truncating authentication tags. - * - * \param ctx EAX context structure. - * \param tag tag value to compare with. - * \param len tag length (in bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ -uint32_t br_eax_check_tag_trunc(br_eax_context *ctx, - const void *tag, size_t len); - -/** - * \brief Class instance for EAX. - */ -extern const br_aead_class br_eax_vtable; - -/** - * \brief Context structure for CCM. - * - * CCM is an AEAD mode that combines a block cipher in CTR mode with - * CBC-MAC using the same block cipher and the same key, to provide - * authenticated encryption: - * - * - Any block cipher with 16-byte blocks can be used with CCM - * (technically, other block sizes are defined as well, but this - * is not implemented by these functions; shorter blocks also - * imply numerous security issues). - * - * - The authentication tag length, and plaintext length, MUST be - * known when starting processing data. Plaintext and ciphertext - * can still be provided by chunks, but the total size must match - * the value provided upon initialisation. - * - * - The nonce length is constrained between 7 and 13 bytes (inclusive). - * Furthermore, the plaintext length, when encoded, must fit over - * 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then - * the plaintext length cannot exceed 65535 bytes. - * - * - Additional authenticated data length is practically unlimited - * (formal limit is at 2^64 bytes). - * - * - The authentication tag has length 4 to 16 bytes (even values only). - * - * The CCM initialisation function receives as parameter an - * _initialised_ block cipher implementation context, with the secret - * key already set. A pointer to that context will be kept within the - * CCM context structure. It is up to the caller to allocate and - * initialise that block cipher context. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - const br_block_ctrcbc_class **bctx; - unsigned char ctr[16]; - unsigned char cbcmac[16]; - unsigned char tagmask[16]; - unsigned char buf[16]; - size_t ptr; - size_t tag_len; -#endif -} br_ccm_context; - -/** - * \brief Initialize a CCM context. - * - * A block cipher implementation, with its initialised context - * structure, is provided. The block cipher MUST use 16-byte blocks in - * CTR + CBC-MAC mode, and its secret key MUST have been already set in - * the provided context. The parameters are linked in the CCM context. - * - * After this function has been called, the `br_ccm_reset()` function must - * be called, to provide the nonce for CCM computation. - * - * \param ctx CCM context structure. - * \param bctx block cipher context (already initialised with secret key). - */ -void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx); - -/** - * \brief Reset a CCM context. - * - * This function resets an already initialised CCM context for a new - * computation run. Implementations and keys are conserved. This function - * can be called at any time; it cancels any ongoing CCM computation that - * uses the provided context structure. - * - * The `aad_len` parameter contains the total length, in bytes, of the - * additional authenticated data. It may be zero. That length MUST be - * exact. - * - * The `data_len` parameter contains the total length, in bytes, of the - * data that will be injected (plaintext or ciphertext). That length MUST - * be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)). - * - * The nonce length (`nonce_len`), in bytes, must be in the 7..13 range - * (inclusive). - * - * The tag length (`tag_len`), in bytes, must be in the 4..16 range, and - * be an even integer. Short tags mechanically allow for higher forgery - * probabilities; hence, tag sizes smaller than 12 bytes shall be used only - * with care. - * - * It is critical to CCM security that nonce values are not repeated for - * the same encryption key. Random generation of nonces is not generally - * recommended, due to the relatively small maximum nonce value. - * - * Returned value is 1 on success, 0 on error. An error is reported if - * the tag or nonce length is out of range, or if the - * plaintext/ciphertext length cannot be encoded with the specified - * nonce length. - * - * \param ctx CCM context structure. - * \param nonce CCM nonce to use. - * \param nonce_len CCM nonce length (in bytes, 7 to 13). - * \param aad_len additional authenticated data length (in bytes). - * \param data_len plaintext/ciphertext length (in bytes). - * \param tag_len tag length (in bytes). - * \return 1 on success, 0 on error. - */ -int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, - uint64_t aad_len, uint64_t data_len, size_t tag_len); - -/** - * \brief Inject additional authenticated data into CCM. - * - * The provided data is injected into a running CCM computation. Additional - * data must be injected _before_ the call to `br_ccm_flip()`. - * Additional data can be injected in several chunks of arbitrary length, - * but the total amount MUST exactly match the value which was provided - * to `br_ccm_reset()`. - * - * \param ctx CCM context structure. - * \param data pointer to additional authenticated data. - * \param len length of additional authenticated data (in bytes). - */ -void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len); - -/** - * \brief Finish injection of additional authenticated data into CCM. - * - * This function MUST be called before beginning the actual encryption - * or decryption (with `br_ccm_run()`), even if no additional authenticated - * data was injected. No additional authenticated data may be injected - * after this function call. - * - * \param ctx CCM context structure. - */ -void br_ccm_flip(br_ccm_context *ctx); - -/** - * \brief Encrypt or decrypt some data with CCM. - * - * Data encryption or decryption can be done after `br_ccm_flip()` - * has been called on the context. If `encrypt` is non-zero, then the - * provided data shall be plaintext, and it is encrypted in place. - * Otherwise, the data shall be ciphertext, and it is decrypted in place. - * - * Data may be provided in several chunks of arbitrary length, provided - * that the total length exactly matches the length provided to the - * `br_ccm_reset()` call. - * - * \param ctx CCM context structure. - * \param encrypt non-zero for encryption, zero for decryption. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len); - -/** - * \brief Compute CCM authentication tag. - * - * Compute the CCM authentication tag. This call terminates the CCM - * run: all data must have been injected with `br_ccm_run()` (in zero, - * one or more successive calls). After this function has been called, - * no more data can br processed; a `br_ccm_reset()` call is required - * to start a new message. - * - * The tag length was provided upon context initialisation (last call - * to `br_ccm_reset()`); it is returned by this function. - * - * The tag value must normally be sent along with the encrypted data. - * When decrypting, the tag value must be recomputed and compared with - * the received tag: if the two tag values differ, then either the tag - * or the encrypted data was altered in transit. As an alternative to - * this function, the `br_ccm_check_tag()` function can be used to - * compute and check the tag value. - * - * \param ctx CCM context structure. - * \param tag destination buffer for the tag (up to 16 bytes). - * \return the tag length (in bytes). - */ -size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag); - -/** - * \brief Compute and check CCM authentication tag. - * - * This function is an alternative to `br_ccm_get_tag()`, normally used - * on the receiving end (i.e. when decrypting value). The tag value is - * recomputed and compared with the provided tag value. If they match, 1 - * is returned; on mismatch, 0 is returned. A returned value of 0 means - * that the data or the tag was altered in transit, normally leading to - * wholesale rejection of the complete message. - * - * \param ctx CCM context structure. - * \param tag tag value to compare with (up to 16 bytes). - * \return 1 on success (exact match of tag value), 0 otherwise. - */ -uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_block.h b/src/tls/bearssl/bearssl_block.h deleted file mode 100644 index 683a4906d..000000000 --- a/src/tls/bearssl/bearssl_block.h +++ /dev/null @@ -1,2618 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_BLOCK_H__ -#define BR_BEARSSL_BLOCK_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_block.h - * - * # Block Ciphers and Symmetric Ciphers - * - * This file documents the API for block ciphers and other symmetric - * ciphers. - * - * - * ## Procedural API - * - * For a block cipher implementation, up to three separate sets of - * functions are provided, for CBC encryption, CBC decryption, and CTR - * encryption/decryption. Each set has its own context structure, - * initialised with the encryption key. - * - * For CBC encryption and decryption, the data to encrypt or decrypt is - * referenced as a sequence of blocks. The implementations assume that - * there is no partial block; no padding is applied or removed. The - * caller is responsible for handling any kind of padding. - * - * Function for CTR encryption are defined only for block ciphers with - * blocks of 16 bytes or more (i.e. AES, but not DES/3DES). - * - * Each implemented block cipher is identified by an "internal name" - * from which are derived the names of structures and functions that - * implement the cipher. For the block cipher of internal name "`xxx`", - * the following are defined: - * - * - `br_xxx_BLOCK_SIZE` - * - * A macro that evaluates to the block size (in bytes) of the - * cipher. For all implemented block ciphers, this value is a - * power of two. - * - * - `br_xxx_cbcenc_keys` - * - * Context structure that contains the subkeys resulting from the key - * expansion. These subkeys are appropriate for CBC encryption. The - * structure first field is called `vtable` and points to the - * appropriate OOP structure. - * - * - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` - * - * Perform key expansion: subkeys for CBC encryption are computed and - * written in the provided context structure. The key length MUST be - * adequate for the implemented block cipher. This function also sets - * the `vtable` field. - * - * - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)` - * - * Perform CBC encryption of `len` bytes, in place. The encrypted data - * replaces the cleartext. `len` MUST be a multiple of the block length - * (if it is not, the function may loop forever or overflow a buffer). - * The IV is provided with the `iv` pointer; it is also updated with - * a copy of the last encrypted block. - * - * - `br_xxx_cbcdec_keys` - * - * Context structure that contains the subkeys resulting from the key - * expansion. These subkeys are appropriate for CBC decryption. The - * structure first field is called `vtable` and points to the - * appropriate OOP structure. - * - * - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)` - * - * Perform key expansion: subkeys for CBC decryption are computed and - * written in the provided context structure. The key length MUST be - * adequate for the implemented block cipher. This function also sets - * the `vtable` field. - * - * - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)` - * - * Perform CBC decryption of `len` bytes, in place. The decrypted data - * replaces the ciphertext. `len` MUST be a multiple of the block length - * (if it is not, the function may loop forever or overflow a buffer). - * The IV is provided with the `iv` pointer; it is also updated with - * a copy of the last _encrypted_ block. - * - * - `br_xxx_ctr_keys` - * - * Context structure that contains the subkeys resulting from the key - * expansion. These subkeys are appropriate for CTR encryption and - * decryption. The structure first field is called `vtable` and - * points to the appropriate OOP structure. - * - * - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` - * - * Perform key expansion: subkeys for CTR encryption and decryption - * are computed and written in the provided context structure. The - * key length MUST be adequate for the implemented block cipher. This - * function also sets the `vtable` field. - * - * - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`) - * - * Perform CTR encryption/decryption of some data. Processing is done - * "in place" (the output data replaces the input data). This function - * implements the "standard incrementing function" from NIST SP800-38A, - * annex B: the IV length shall be 4 bytes less than the block size - * (i.e. 12 bytes for AES) and the counter is the 32-bit value starting - * with `cc`. The data length (`len`) is not necessarily a multiple of - * the block size. The new counter value is returned, which supports - * chunked processing, provided that each chunk length (except possibly - * the last one) is a multiple of the block size. - * - * - `br_xxx_ctrcbc_keys` - * - * Context structure that contains the subkeys resulting from the - * key expansion. These subkeys are appropriate for doing combined - * CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX - * authenticated encryption modes. The structure first field is - * called `vtable` and points to the appropriate OOP structure. - * - * - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)` - * - * Perform key expansion: subkeys for combined CTR - * encryption/decryption and CBC-MAC are computed and written in the - * provided context structure. The key length MUST be adequate for - * the implemented block cipher. This function also sets the - * `vtable` field. - * - * - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` - * - * Perform CTR encryption of some data, and CBC-MAC. Processing is - * done "in place" (the output data replaces the input data). This - * function applies CTR encryption on the data, using a full - * block-size counter (i.e. for 128-bit blocks, the counter is - * incremented as a 128-bit value). The 'ctr' array contains the - * initial value for the counter (used in the first block) and it is - * updated with the new value after data processing. The 'cbcmac' - * value shall point to a block-sized value which is used as IV for - * CBC-MAC, computed over the encrypted data (output of CTR - * encryption); the resulting CBC-MAC is written over 'cbcmac' on - * output. - * - * The data length MUST be a multiple of the block size. - * - * - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)` - * - * Perform CTR decryption of some data, and CBC-MAC. Processing is - * done "in place" (the output data replaces the input data). This - * function applies CTR decryption on the data, using a full - * block-size counter (i.e. for 128-bit blocks, the counter is - * incremented as a 128-bit value). The 'ctr' array contains the - * initial value for the counter (used in the first block) and it is - * updated with the new value after data processing. The 'cbcmac' - * value shall point to a block-sized value which is used as IV for - * CBC-MAC, computed over the encrypted data (input of CTR - * encryption); the resulting CBC-MAC is written over 'cbcmac' on - * output. - * - * The data length MUST be a multiple of the block size. - * - * - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)` - * - * Perform CTR encryption or decryption of the provided data. The - * data is processed "in place" (the output data replaces the input - * data). A full block-sized counter is applied (i.e. for 128-bit - * blocks, the counter is incremented as a 128-bit value). The 'ctr' - * array contains the initial value for the counter (used in the - * first block), and it is updated with the new value after data - * processing. - * - * The data length MUST be a multiple of the block size. - * - * - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)` - * - * Compute CBC-MAC over the provided data. The IV for CBC-MAC is - * provided as 'cbcmac'; the output is written over the same array. - * The data itself is untouched. The data length MUST be a multiple - * of the block size. - * - * - * It shall be noted that the key expansion functions return `void`. If - * the provided key length is not allowed, then there will be no error - * reporting; implementations need not validate the key length, thus an - * invalid key length may result in undefined behaviour (e.g. buffer - * overflow). - * - * Subkey structures contain no interior pointer, and no external - * resources are allocated upon key expansion. They can thus be - * discarded without any explicit deallocation. - * - * - * ## Object-Oriented API - * - * Each context structure begins with a field (called `vtable`) that - * points to an instance of a structure that references the relevant - * functions through pointers. Each such structure contains the - * following: - * - * - `context_size` - * - * The size (in bytes) of the context structure for subkeys. - * - * - `block_size` - * - * The cipher block size (in bytes). - * - * - `log_block_size` - * - * The base-2 logarithm of cipher block size (e.g. 4 for blocks - * of 16 bytes). - * - * - `init` - * - * Pointer to the key expansion function. - * - * - `run` - * - * Pointer to the encryption/decryption function. - * - * For combined CTR/CBC-MAC encryption, the `vtable` has a slightly - * different structure: - * - * - `context_size` - * - * The size (in bytes) of the context structure for subkeys. - * - * - `block_size` - * - * The cipher block size (in bytes). - * - * - `log_block_size` - * - * The base-2 logarithm of cipher block size (e.g. 4 for blocks - * of 16 bytes). - * - * - `init` - * - * Pointer to the key expansion function. - * - * - `encrypt` - * - * Pointer to the CTR encryption + CBC-MAC function. - * - * - `decrypt` - * - * Pointer to the CTR decryption + CBC-MAC function. - * - * - `ctr` - * - * Pointer to the CTR encryption/decryption function. - * - * - `mac` - * - * Pointer to the CBC-MAC function. - * - * For block cipher "`xxx`", static, constant instances of these - * structures are defined, under the names: - * - * - `br_xxx_cbcenc_vtable` - * - `br_xxx_cbcdec_vtable` - * - `br_xxx_ctr_vtable` - * - `br_xxx_ctrcbc_vtable` - * - * - * ## Implemented Block Ciphers - * - * Provided implementations are: - * - * | Name | Function | Block Size (bytes) | Key lengths (bytes) | - * | :-------- | :------- | :----------------: | :-----------------: | - * | aes_big | AES | 16 | 16, 24 and 32 | - * | aes_small | AES | 16 | 16, 24 and 32 | - * | aes_ct | AES | 16 | 16, 24 and 32 | - * | aes_ct64 | AES | 16 | 16, 24 and 32 | - * | aes_x86ni | AES | 16 | 16, 24 and 32 | - * | aes_pwr8 | AES | 16 | 16, 24 and 32 | - * | des_ct | DES/3DES | 8 | 8, 16 and 24 | - * | des_tab | DES/3DES | 8 | 8, 16 and 24 | - * - * **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8, - * 16 and 24 bytes), but some of the bits are ignored by the algorithm, so - * the _effective_ key lengths, from a security point of view, are 56, - * 112 and 168 bits, respectively. - * - * `aes_big` is a "classical" AES implementation, using tables. It - * is fast but not constant-time, since it makes data-dependent array - * accesses. - * - * `aes_small` is an AES implementation optimized for code size. It - * is substantially slower than `aes_big`; it is not constant-time - * either. - * - * `aes_ct` is a constant-time implementation of AES; its code is about - * as big as that of `aes_big`, while its performance is comparable to - * that of `aes_small`. However, it is constant-time. This - * implementation should thus be considered to be the "default" AES in - * BearSSL, to be used unless the operational context guarantees that a - * non-constant-time implementation is safe, or an architecture-specific - * constant-time implementation can be used (e.g. using dedicated - * hardware opcodes). - * - * `aes_ct64` is another constant-time implementation of AES. It is - * similar to `aes_ct` but uses 64-bit values. On 32-bit machines, - * `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has - * a larger footprint; however, on 64-bit architectures, `aes_ct64` - * is typically twice faster than `aes_ct` for modes that allow parallel - * operations (i.e. CTR, and CBC decryption, but not CBC encryption). - * - * `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It - * uses the AES-NI opcodes when available. - * - * `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and - * 64-bit, both little-endian and big-endian). It uses the AES opcodes - * present in POWER8 and later. - * - * `des_tab` is a classic, table-based implementation of DES/3DES. It - * is not constant-time. - * - * `des_ct` is an constant-time implementation of DES/3DES. It is - * substantially slower than `des_tab`. - * - * ## ChaCha20 and Poly1305 - * - * ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They - * are described in [RFC 7539](https://tools.ietf.org/html/rfc7539). - * - * Two function pointer types are defined: - * - * - `br_chacha20_run` describes a function that implements ChaCha20 - * only. - * - * - `br_poly1305_run` describes an implementation of Poly1305, - * in the AEAD combination with ChaCha20 specified in RFC 7539 - * (the ChaCha20 implementation is provided as a function pointer). - * - * `chacha20_ct` is a straightforward implementation of ChaCha20 in - * plain C; it is constant-time, small, and reasonably fast. - * - * `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that - * support these opcodes). It is faster than `chacha20_ct`. - * - * `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD - * construction, where the Poly1305 part is performed with mixed 32-bit - * multiplications (operands are 32-bit, result is 64-bit). - * - * `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit - * multiplications (32-bit operands, 32-bit result). It is slower than - * `poly1305_ctmul`, except on some specific architectures such as - * the ARM Cortex M0+. - * - * `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit - * multiplications (operands are 64-bit, result is 128-bit) on 64-bit - * platforms that support such operations. - * - * `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15" - * big integer implementation. It is meant mostly for testing purposes, - * although it can help with saving a few hundred bytes of code footprint - * on systems where code size is scarce. - */ - -/** - * \brief Class type for CBC encryption implementations. - * - * A `br_block_cbcenc_class` instance points to the functions implementing - * a specific block cipher, when used in CBC mode for encrypting data. - */ -typedef struct br_block_cbcenc_class_ br_block_cbcenc_class; -struct br_block_cbcenc_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate - * for containing subkeys. - */ - size_t context_size; - - /** - * \brief Size of individual blocks (in bytes). - */ - unsigned block_size; - - /** - * \brief Base-2 logarithm of the size of individual blocks, - * expressed in bytes. - */ - unsigned log_block_size; - - /** - * \brief Initialisation function. - * - * This function sets the `vtable` field in the context structure. - * The key length MUST be one of the key lengths supported by - * the implementation. - * - * \param ctx context structure to initialise. - * \param key secret key. - * \param key_len key length (in bytes). - */ - void (*init)(const br_block_cbcenc_class **ctx, - const void *key, size_t key_len); - - /** - * \brief Run the CBC encryption. - * - * The `iv` parameter points to the IV for this run; it is - * updated with a copy of the last encrypted block. The data - * is encrypted "in place"; its length (`len`) MUST be a - * multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param iv IV for CBC encryption (updated). - * \param data data to encrypt. - * \param len data length (in bytes, multiple of block size). - */ - void (*run)(const br_block_cbcenc_class *const *ctx, - void *iv, void *data, size_t len); -}; - -/** - * \brief Class type for CBC decryption implementations. - * - * A `br_block_cbcdec_class` instance points to the functions implementing - * a specific block cipher, when used in CBC mode for decrypting data. - */ -typedef struct br_block_cbcdec_class_ br_block_cbcdec_class; -struct br_block_cbcdec_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate - * for containing subkeys. - */ - size_t context_size; - - /** - * \brief Size of individual blocks (in bytes). - */ - unsigned block_size; - - /** - * \brief Base-2 logarithm of the size of individual blocks, - * expressed in bytes. - */ - unsigned log_block_size; - - /** - * \brief Initialisation function. - * - * This function sets the `vtable` field in the context structure. - * The key length MUST be one of the key lengths supported by - * the implementation. - * - * \param ctx context structure to initialise. - * \param key secret key. - * \param key_len key length (in bytes). - */ - void (*init)(const br_block_cbcdec_class **ctx, - const void *key, size_t key_len); - - /** - * \brief Run the CBC decryption. - * - * The `iv` parameter points to the IV for this run; it is - * updated with a copy of the last encrypted block. The data - * is decrypted "in place"; its length (`len`) MUST be a - * multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param iv IV for CBC decryption (updated). - * \param data data to decrypt. - * \param len data length (in bytes, multiple of block size). - */ - void (*run)(const br_block_cbcdec_class *const *ctx, - void *iv, void *data, size_t len); -}; - -/** - * \brief Class type for CTR encryption/decryption implementations. - * - * A `br_block_ctr_class` instance points to the functions implementing - * a specific block cipher, when used in CTR mode for encrypting or - * decrypting data. - */ -typedef struct br_block_ctr_class_ br_block_ctr_class; -struct br_block_ctr_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate - * for containing subkeys. - */ - size_t context_size; - - /** - * \brief Size of individual blocks (in bytes). - */ - unsigned block_size; - - /** - * \brief Base-2 logarithm of the size of individual blocks, - * expressed in bytes. - */ - unsigned log_block_size; - - /** - * \brief Initialisation function. - * - * This function sets the `vtable` field in the context structure. - * The key length MUST be one of the key lengths supported by - * the implementation. - * - * \param ctx context structure to initialise. - * \param key secret key. - * \param key_len key length (in bytes). - */ - void (*init)(const br_block_ctr_class **ctx, - const void *key, size_t key_len); - - /** - * \brief Run the CTR encryption or decryption. - * - * The `iv` parameter points to the IV for this run; its - * length is exactly 4 bytes less than the block size (e.g. - * 12 bytes for AES/CTR). The IV is combined with a 32-bit - * block counter to produce the block value which is processed - * with the block cipher. - * - * The data to encrypt or decrypt is updated "in place". Its - * length (`len` bytes) is not required to be a multiple of - * the block size; if the final block is partial, then the - * corresponding key stream bits are dropped. - * - * The resulting counter value is returned. - * - * \param ctx context structure (already initialised). - * \param iv IV for CTR encryption/decryption. - * \param cc initial value for the block counter. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \return the new block counter value. - */ - uint32_t (*run)(const br_block_ctr_class *const *ctx, - const void *iv, uint32_t cc, void *data, size_t len); -}; - -/** - * \brief Class type for combined CTR and CBC-MAC implementations. - * - * A `br_block_ctrcbc_class` instance points to the functions implementing - * a specific block cipher, when used in CTR mode for encrypting or - * decrypting data, along with CBC-MAC. - */ -typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class; -struct br_block_ctrcbc_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate - * for containing subkeys. - */ - size_t context_size; - - /** - * \brief Size of individual blocks (in bytes). - */ - unsigned block_size; - - /** - * \brief Base-2 logarithm of the size of individual blocks, - * expressed in bytes. - */ - unsigned log_block_size; - - /** - * \brief Initialisation function. - * - * This function sets the `vtable` field in the context structure. - * The key length MUST be one of the key lengths supported by - * the implementation. - * - * \param ctx context structure to initialise. - * \param key secret key. - * \param key_len key length (in bytes). - */ - void (*init)(const br_block_ctrcbc_class **ctx, - const void *key, size_t key_len); - - /** - * \brief Run the CTR encryption + CBC-MAC. - * - * The `ctr` parameter points to the counter; its length shall - * be equal to the block size. It is updated by this function - * as encryption proceeds. - * - * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC - * is computed over the encrypted data (output of CTR - * encryption). Its length shall be equal to the block size. The - * computed CBC-MAC value is written over the `cbcmac` array. - * - * The data to encrypt is updated "in place". Its length (`len` - * bytes) MUST be a multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param ctr counter for CTR encryption (initial and final). - * \param cbcmac IV and output buffer for CBC-MAC. - * \param data data to encrypt. - * \param len data length (in bytes). - */ - void (*encrypt)(const br_block_ctrcbc_class *const *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - - /** - * \brief Run the CTR decryption + CBC-MAC. - * - * The `ctr` parameter points to the counter; its length shall - * be equal to the block size. It is updated by this function - * as decryption proceeds. - * - * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC - * is computed over the encrypted data (i.e. before CTR - * decryption). Its length shall be equal to the block size. The - * computed CBC-MAC value is written over the `cbcmac` array. - * - * The data to decrypt is updated "in place". Its length (`len` - * bytes) MUST be a multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param ctr counter for CTR encryption (initial and final). - * \param cbcmac IV and output buffer for CBC-MAC. - * \param data data to decrypt. - * \param len data length (in bytes). - */ - void (*decrypt)(const br_block_ctrcbc_class *const *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - - /** - * \brief Run the CTR encryption/decryption only. - * - * The `ctr` parameter points to the counter; its length shall - * be equal to the block size. It is updated by this function - * as decryption proceeds. - * - * The data to decrypt is updated "in place". Its length (`len` - * bytes) MUST be a multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param ctr counter for CTR encryption (initial and final). - * \param data data to decrypt. - * \param len data length (in bytes). - */ - void (*ctr)(const br_block_ctrcbc_class *const *ctx, - void *ctr, void *data, size_t len); - - /** - * \brief Run the CBC-MAC only. - * - * The `cbcmac` parameter points to the IV for CBC-MAC. The MAC - * is computed over the encrypted data (i.e. before CTR - * decryption). Its length shall be equal to the block size. The - * computed CBC-MAC value is written over the `cbcmac` array. - * - * The data is unmodified. Its length (`len` bytes) MUST be a - * multiple of the block size. - * - * \param ctx context structure (already initialised). - * \param cbcmac IV and output buffer for CBC-MAC. - * \param data data to decrypt. - * \param len data length (in bytes). - */ - void (*mac)(const br_block_ctrcbc_class *const *ctx, - void *cbcmac, const void *data, size_t len); -}; - -/* - * Traditional, table-based AES implementation. It is fast, but uses - * internal tables (in particular a 1 kB table for encryption, another - * 1 kB table for decryption, and a 256-byte table for key schedule), - * and it is not constant-time. In contexts where cache-timing attacks - * apply, this implementation may leak the secret key. - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_big_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_big` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_big_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_big` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_big_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_big_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_big` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_big_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_big` implementation). - */ -extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_big` implementation). - */ -extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_big` implementation). - */ -extern const br_block_ctr_class br_aes_big_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_big` implementation). - */ -extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_big` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_big` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_big` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_big` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to encrypt or decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_big` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/* - * AES implementation optimized for size. It is slower than the - * traditional table-based AES implementation, but requires much less - * code. It still uses data-dependent table accesses (albeit within a - * much smaller 256-byte table), which makes it conceptually vulnerable - * to cache-timing attacks. - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_small_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_small` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_small_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_small` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_small_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_small_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_small` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_small_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_small` implementation). - */ -extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_small` implementation). - */ -extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_small` implementation). - */ -extern const br_block_ctr_class br_aes_small_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_small` implementation). - */ -extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_small` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_small` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_small` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_small` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_small` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/* - * Constant-time AES implementation. Its size is similar to that of - * 'aes_big', and its performance is similar to that of 'aes_small' (faster - * decryption, slower encryption). However, it is constant-time, i.e. - * immune to cache-timing and similar attacks. - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_ct_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_ct_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_ct_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_ct_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[60]; - unsigned num_rounds; -#endif -} br_aes_ct_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_ct` implementation). - */ -extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_ct` implementation). - */ -extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_ct` implementation). - */ -extern const br_block_ctr_class br_aes_ct_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_ct` implementation). - */ -extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_ct` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/* - * 64-bit constant-time AES implementation. It is similar to 'aes_ct' - * but uses 64-bit registers, making it about twice faster than 'aes_ct' - * on 64-bit platforms, while remaining constant-time and with a similar - * code size. (The doubling in performance is only for CBC decryption - * and CTR mode; CBC encryption is non-parallel and cannot benefit from - * the larger registers.) - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_ct64_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t skey[30]; - unsigned num_rounds; -#endif -} br_aes_ct64_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t skey[30]; - unsigned num_rounds; -#endif -} br_aes_ct64_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t skey[30]; - unsigned num_rounds; -#endif -} br_aes_ct64_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t skey[30]; - unsigned num_rounds; -#endif -} br_aes_ct64_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_ct64` implementation). - */ -extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_ct64` implementation). - */ -extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_ct64` implementation). - */ -extern const br_block_ctr_class br_aes_ct64_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_ct64` implementation). - */ -extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_ct64` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_ct64` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_ct64` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_ct64` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_ct64` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/* - * AES implementation using AES-NI opcodes (x86 platform). - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_x86ni_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_x86ni_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_x86ni_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_x86ni_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_x86ni_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_x86ni` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`. - */ -extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_x86ni` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`. - */ -extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_x86ni` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`. - */ -extern const br_block_ctr_class br_aes_x86ni_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_x86ni` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`. - */ -extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_x86ni` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_x86ni` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_x86ni` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_x86ni` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_x86ni` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/** - * \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if - * available. - * - * This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if - * that implementation was compiled in the library _and_ the x86 AES - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`. - */ -const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void); - -/** - * \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if - * available. - * - * This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if - * that implementation was compiled in the library _and_ the x86 AES - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`. - */ -const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void); - -/** - * \brief Obtain the `aes_x86ni` AES-CTR implementation, if available. - * - * This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if - * that implementation was compiled in the library _and_ the x86 AES - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. - */ -const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void); - -/** - * \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if - * available. - * - * This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if - * that implementation was compiled in the library _and_ the x86 AES - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_x86ni` AES-CTR implementation, or `NULL`. - */ -const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void); - -/* - * AES implementation using POWER8 opcodes. - */ - -/** \brief AES block size (16 bytes). */ -#define br_aes_pwr8_BLOCK_SIZE 16 - -/** - * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_pwr8_cbcenc_keys; - -/** - * \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_pwr8_cbcdec_keys; - -/** - * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption - * and decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctr_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_pwr8_ctr_keys; - -/** - * \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption - * and decryption + CBC-MAC). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_ctrcbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - union { - unsigned char skni[16 * 15]; - } skey; - unsigned num_rounds; -#endif -} br_aes_pwr8_ctrcbc_keys; - -/** - * \brief Class instance for AES CBC encryption (`aes_pwr8` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`. - */ -extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable; - -/** - * \brief Class instance for AES CBC decryption (`aes_pwr8` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`. - */ -extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable; - -/** - * \brief Class instance for AES CTR encryption and decryption - * (`aes_pwr8` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`. - */ -extern const br_block_ctr_class br_aes_pwr8_ctr_vtable; - -/** - * \brief Class instance for AES CTR encryption/decryption + CBC-MAC - * (`aes_pwr8` implementation). - * - * Since this implementation might be omitted from the library, or the - * AES opcode unavailable on the current CPU, a pointer to this class - * instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`. - */ -extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable; - -/** - * \brief Context initialisation (key schedule) for AES CBC encryption - * (`aes_pwr8` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CBC decryption - * (`aes_pwr8` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR encryption - * and decryption (`aes_pwr8` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for AES CTR + CBC-MAC - * (`aes_pwr8` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 16). - */ -void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CTR encryption and decryption with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (constant, 12 bytes). - * \param cc initial block counter value. - * \param data data to decrypt (updated). - * \param len data length (in bytes). - * \return new block counter value. - */ -uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *cbcmac, void *data, size_t len); - -/** - * \brief CTR encryption/decryption with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param ctr counter for CTR (16 bytes, updated). - * \param data data to MAC (updated). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx, - void *ctr, void *data, size_t len); - -/** - * \brief CBC-MAC with AES (`aes_pwr8` implementation). - * - * \param ctx context (already initialised). - * \param cbcmac IV for CBC-MAC (updated). - * \param data data to MAC (unmodified). - * \param len data length (in bytes, MUST be a multiple of 16). - */ -void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx, - void *cbcmac, const void *data, size_t len); - -/** - * \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if - * available. - * - * This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if - * that implementation was compiled in the library _and_ the POWER8 - * crypto opcodes are available on the currently running CPU. If either - * of these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`. - */ -const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void); - -/** - * \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if - * available. - * - * This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if - * that implementation was compiled in the library _and_ the POWER8 - * crypto opcodes are available on the currently running CPU. If either - * of these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`. - */ -const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void); - -/** - * \brief Obtain the `aes_pwr8` AES-CTR implementation, if available. - * - * This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that - * implementation was compiled in the library _and_ the POWER8 crypto - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. - */ -const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void); - -/** - * \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if - * available. - * - * This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if - * that implementation was compiled in the library _and_ the POWER8 AES - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `NULL`. - * - * \return the `aes_pwr8` AES-CTR implementation, or `NULL`. - */ -const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void); - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CBC encryption) for all AES implementations. - */ -typedef union { - const br_block_cbcenc_class *vtable; - br_aes_big_cbcenc_keys c_big; - br_aes_small_cbcenc_keys c_small; - br_aes_ct_cbcenc_keys c_ct; - br_aes_ct64_cbcenc_keys c_ct64; - br_aes_x86ni_cbcenc_keys c_x86ni; - br_aes_pwr8_cbcenc_keys c_pwr8; -} br_aes_gen_cbcenc_keys; - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CBC decryption) for all AES implementations. - */ -typedef union { - const br_block_cbcdec_class *vtable; - br_aes_big_cbcdec_keys c_big; - br_aes_small_cbcdec_keys c_small; - br_aes_ct_cbcdec_keys c_ct; - br_aes_ct64_cbcdec_keys c_ct64; - br_aes_x86ni_cbcdec_keys c_x86ni; - br_aes_pwr8_cbcdec_keys c_pwr8; -} br_aes_gen_cbcdec_keys; - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CTR encryption and decryption) for all AES implementations. - */ -typedef union { - const br_block_ctr_class *vtable; - br_aes_big_ctr_keys c_big; - br_aes_small_ctr_keys c_small; - br_aes_ct_ctr_keys c_ct; - br_aes_ct64_ctr_keys c_ct64; - br_aes_x86ni_ctr_keys c_x86ni; - br_aes_pwr8_ctr_keys c_pwr8; -} br_aes_gen_ctr_keys; - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations. - */ -typedef union { - const br_block_ctrcbc_class *vtable; - br_aes_big_ctrcbc_keys c_big; - br_aes_small_ctrcbc_keys c_small; - br_aes_ct_ctrcbc_keys c_ct; - br_aes_ct64_ctrcbc_keys c_ct64; - br_aes_x86ni_ctrcbc_keys c_x86ni; - br_aes_pwr8_ctrcbc_keys c_pwr8; -} br_aes_gen_ctrcbc_keys; - -/* - * Traditional, table-based implementation for DES/3DES. Since tables are - * used, cache-timing attacks are conceptually possible. - */ - -/** \brief DES/3DES block size (8 bytes). */ -#define br_des_tab_BLOCK_SIZE 8 - -/** - * \brief Context for DES subkeys (`des_tab` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[96]; - unsigned num_rounds; -#endif -} br_des_tab_cbcenc_keys; - -/** - * \brief Context for DES subkeys (`des_tab` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[96]; - unsigned num_rounds; -#endif -} br_des_tab_cbcdec_keys; - -/** - * \brief Class instance for DES CBC encryption (`des_tab` implementation). - */ -extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable; - -/** - * \brief Class instance for DES CBC decryption (`des_tab` implementation). - */ -extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable; - -/** - * \brief Context initialisation (key schedule) for DES CBC encryption - * (`des_tab` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for DES CBC decryption - * (`des_tab` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with DES (`des_tab` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 8). - */ -void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with DES (`des_tab` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 8). - */ -void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/* - * Constant-time implementation for DES/3DES. It is substantially slower - * (by a factor of about 4x), but also immune to cache-timing attacks. - */ - -/** \brief DES/3DES block size (8 bytes). */ -#define br_des_ct_BLOCK_SIZE 8 - -/** - * \brief Context for DES subkeys (`des_ct` implementation, CBC encryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcenc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[96]; - unsigned num_rounds; -#endif -} br_des_ct_cbcenc_keys; - -/** - * \brief Context for DES subkeys (`des_ct` implementation, CBC decryption). - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** \brief Pointer to vtable for this context. */ - const br_block_cbcdec_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint32_t skey[96]; - unsigned num_rounds; -#endif -} br_des_ct_cbcdec_keys; - -/** - * \brief Class instance for DES CBC encryption (`des_ct` implementation). - */ -extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable; - -/** - * \brief Class instance for DES CBC decryption (`des_ct` implementation). - */ -extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable; - -/** - * \brief Context initialisation (key schedule) for DES CBC encryption - * (`des_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, - const void *key, size_t len); - -/** - * \brief Context initialisation (key schedule) for DES CBC decryption - * (`des_ct` implementation). - * - * \param ctx context to initialise. - * \param key secret key. - * \param len secret key length (in bytes). - */ -void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, - const void *key, size_t len); - -/** - * \brief CBC encryption with DES (`des_ct` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to encrypt (updated). - * \param len data length (in bytes, MUST be multiple of 8). - */ -void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv, - void *data, size_t len); - -/** - * \brief CBC decryption with DES (`des_ct` implementation). - * - * \param ctx context (already initialised). - * \param iv IV (updated). - * \param data data to decrypt (updated). - * \param len data length (in bytes, MUST be multiple of 8). - */ -void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv, - void *data, size_t len); - -/* - * These structures are large enough to accommodate subkeys for all - * DES/3DES implementations. - */ - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CBC encryption) for all DES implementations. - */ -typedef union { - const br_block_cbcenc_class *vtable; - br_des_tab_cbcenc_keys tab; - br_des_ct_cbcenc_keys ct; -} br_des_gen_cbcenc_keys; - -/** - * \brief Aggregate structure large enough to be used as context for - * subkeys (CBC decryption) for all DES implementations. - */ -typedef union { - const br_block_cbcdec_class *vtable; - br_des_tab_cbcdec_keys c_tab; - br_des_ct_cbcdec_keys c_ct; -} br_des_gen_cbcdec_keys; - -/** - * \brief Type for a ChaCha20 implementation. - * - * An implementation follows the description in RFC 7539: - * - * - Key is 256 bits (`key` points to exactly 32 bytes). - * - * - IV is 96 bits (`iv` points to exactly 12 bytes). - * - * - Block counter is over 32 bits and starts at value `cc`; the - * resulting value is returned. - * - * Data (pointed to by `data`, of length `len`) is encrypted/decrypted - * in place. If `len` is not a multiple of 64, then the excess bytes from - * the last block processing are dropped (therefore, "chunked" processing - * works only as long as each non-final chunk has a length multiple of 64). - * - * \param key secret key (32 bytes). - * \param iv IV (12 bytes). - * \param cc initial counter value. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -typedef uint32_t (*br_chacha20_run)(const void *key, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief ChaCha20 implementation (straightforward C code, constant-time). - * - * \see br_chacha20_run - * - * \param key secret key (32 bytes). - * \param iv IV (12 bytes). - * \param cc initial counter value. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -uint32_t br_chacha20_ct_run(const void *key, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief ChaCha20 implementation (SSE2 code, constant-time). - * - * This implementation is available only on x86 platforms, depending on - * compiler support. Moreover, in 32-bit mode, it might not actually run, - * if the underlying hardware does not implement the SSE2 opcode (in - * 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled - * at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain - * a pointer to that function. - * - * \see br_chacha20_run - * - * \param key secret key (32 bytes). - * \param iv IV (12 bytes). - * \param cc initial counter value. - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - */ -uint32_t br_chacha20_sse2_run(const void *key, - const void *iv, uint32_t cc, void *data, size_t len); - -/** - * \brief Obtain the `sse2` ChaCha20 implementation, if available. - * - * This function returns a pointer to `br_chacha20_sse2_run`, if - * that implementation was compiled in the library _and_ the SSE2 - * opcodes are available on the currently running CPU. If either of - * these conditions is not met, then this function returns `0`. - * - * \return the `sse2` ChaCha20 implementation, or `0`. - */ -br_chacha20_run br_chacha20_sse2_get(void); - -/** - * \brief Type for a ChaCha20+Poly1305 AEAD implementation. - * - * The provided data is encrypted or decrypted with ChaCha20. The - * authentication tag is computed on the concatenation of the - * additional data and the ciphertext, with the padding and lengths - * as described in RFC 7539 (section 2.8). - * - * After decryption, the caller is responsible for checking that the - * computed tag matches the expected value. - * - * \param key secret key (32 bytes). - * \param iv nonce (12 bytes). - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \param aad additional authenticated data. - * \param aad_len length of additional authenticated data (in bytes). - * \param tag output buffer for the authentication tag. - * \param ichacha implementation of ChaCha20. - * \param encrypt non-zero for encryption, zero for decryption. - */ -typedef void (*br_poly1305_run)(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt); - -/** - * \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications). - * - * \see br_poly1305_run - * - * \param key secret key (32 bytes). - * \param iv nonce (12 bytes). - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \param aad additional authenticated data. - * \param aad_len length of additional authenticated data (in bytes). - * \param tag output buffer for the authentication tag. - * \param ichacha implementation of ChaCha20. - * \param encrypt non-zero for encryption, zero for decryption. - */ -void br_poly1305_ctmul_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt); - -/** - * \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications). - * - * \see br_poly1305_run - * - * \param key secret key (32 bytes). - * \param iv nonce (12 bytes). - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \param aad additional authenticated data. - * \param aad_len length of additional authenticated data (in bytes). - * \param tag output buffer for the authentication tag. - * \param ichacha implementation of ChaCha20. - * \param encrypt non-zero for encryption, zero for decryption. - */ -void br_poly1305_ctmul32_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt); - -/** - * \brief ChaCha20+Poly1305 AEAD implementation (i15). - * - * This implementation relies on the generic big integer code "i15" - * (which uses pure 32-bit multiplications). As such, it may save a - * little code footprint in a context where "i15" is already included - * (e.g. for elliptic curves or for RSA); however, it is also - * substantially slower than the ctmul and ctmul32 implementations. - * - * \see br_poly1305_run - * - * \param key secret key (32 bytes). - * \param iv nonce (12 bytes). - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \param aad additional authenticated data. - * \param aad_len length of additional authenticated data (in bytes). - * \param tag output buffer for the authentication tag. - * \param ichacha implementation of ChaCha20. - * \param encrypt non-zero for encryption, zero for decryption. - */ -void br_poly1305_i15_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt); - -/** - * \brief ChaCha20+Poly1305 AEAD implementation (ctmulq). - * - * This implementation uses 64-bit multiplications (result over 128 bits). - * It is available only on platforms that offer such a primitive (in - * practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to - * dynamically obtain a pointer to that function, or 0 if not supported. - * - * \see br_poly1305_run - * - * \param key secret key (32 bytes). - * \param iv nonce (12 bytes). - * \param data data to encrypt or decrypt. - * \param len data length (in bytes). - * \param aad additional authenticated data. - * \param aad_len length of additional authenticated data (in bytes). - * \param tag output buffer for the authentication tag. - * \param ichacha implementation of ChaCha20. - * \param encrypt non-zero for encryption, zero for decryption. - */ -void br_poly1305_ctmulq_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt); - -/** - * \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available. - * - * This function returns a pointer to the `br_poly1305_ctmulq_run()` - * function if supported on the current platform; otherwise, it returns 0. - * - * \return the ctmulq ChaCha20+Poly1305 implementation, or 0. - */ -br_poly1305_run br_poly1305_ctmulq_get(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_ec.h b/src/tls/bearssl/bearssl_ec.h deleted file mode 100644 index db22692ee..000000000 --- a/src/tls/bearssl/bearssl_ec.h +++ /dev/null @@ -1,883 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_EC_H__ -#define BR_BEARSSL_EC_H__ - -#include -#include - -#include "bearssl_rand.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_ec.h - * - * # Elliptic Curves - * - * This file documents the EC implementations provided with BearSSL, and - * ECDSA. - * - * ## Elliptic Curve API - * - * Only "named curves" are supported. Each EC implementation supports - * one or several named curves, identified by symbolic identifiers. - * These identifiers are small integers, that correspond to the values - * registered by the - * [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8). - * - * Since all currently defined elliptic curve identifiers are in the 0..31 - * range, it is convenient to encode support of some curves in a 32-bit - * word, such that bit x corresponds to curve of identifier x. - * - * An EC implementation is incarnated by a `br_ec_impl` instance, that - * offers the following fields: - * - * - `supported_curves` - * - * A 32-bit word that documents the identifiers of the curves supported - * by this implementation. - * - * - `generator()` - * - * Callback method that returns a pointer to the conventional generator - * point for that curve. - * - * - `order()` - * - * Callback method that returns a pointer to the subgroup order for - * that curve. That value uses unsigned big-endian encoding. - * - * - `xoff()` - * - * Callback method that returns the offset and length of the X - * coordinate in an encoded point. - * - * - `mul()` - * - * Multiply a curve point with an integer. - * - * - `mulgen()` - * - * Multiply the curve generator with an integer. This may be faster - * than the generic `mul()`. - * - * - `muladd()` - * - * Multiply two curve points by two integers, and return the sum of - * the two products. - * - * All curve points are represented in uncompressed format. The `mul()` - * and `muladd()` methods take care to validate that the provided points - * are really part of the relevant curve subgroup. - * - * For all point multiplication functions, the following holds: - * - * - Functions validate that the provided points are valid members - * of the relevant curve subgroup. An error is reported if that is - * not the case. - * - * - Processing is constant-time, even if the point operands are not - * valid. This holds for both the source and resulting points, and - * the multipliers (integers). Only the byte length of the provided - * multiplier arrays (not their actual value length in bits) may - * leak through timing-based side channels. - * - * - The multipliers (integers) MUST be lower than the subgroup order. - * If this property is not met, then the result is indeterminate, - * but an error value is not ncessearily returned. - * - * - * ## ECDSA - * - * ECDSA signatures have two standard formats, called "raw" and "asn1". - * Internally, such a signature is a pair of modular integers `(r,s)`. - * The "raw" format is the concatenation of the unsigned big-endian - * encodings of these two integers, possibly left-padded with zeros so - * that they have the same encoded length. The "asn1" format is the - * DER encoding of an ASN.1 structure that contains the two integer - * values: - * - * ECDSASignature ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * In general, in all of X.509 and SSL/TLS, the "asn1" format is used. - * BearSSL offers ECDSA implementations for both formats; conversion - * functions between the two formats are also provided. Conversion of a - * "raw" format signature into "asn1" may enlarge a signature by no more - * than 9 bytes for all supported curves; conversely, conversion of an - * "asn1" signature to "raw" may expand the signature but the "raw" - * length will never be more than twice the length of the "asn1" length - * (and usually it will be shorter). - * - * Note that for a given signature, the "raw" format is not fully - * deterministic, in that it does not enforce a minimal common length. - */ - -/* - * Standard curve ID. These ID are equal to the assigned numerical - * identifiers assigned to these curves for TLS: - * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - */ - -/** \brief Identifier for named curve sect163k1. */ -#define BR_EC_sect163k1 1 - -/** \brief Identifier for named curve sect163r1. */ -#define BR_EC_sect163r1 2 - -/** \brief Identifier for named curve sect163r2. */ -#define BR_EC_sect163r2 3 - -/** \brief Identifier for named curve sect193r1. */ -#define BR_EC_sect193r1 4 - -/** \brief Identifier for named curve sect193r2. */ -#define BR_EC_sect193r2 5 - -/** \brief Identifier for named curve sect233k1. */ -#define BR_EC_sect233k1 6 - -/** \brief Identifier for named curve sect233r1. */ -#define BR_EC_sect233r1 7 - -/** \brief Identifier for named curve sect239k1. */ -#define BR_EC_sect239k1 8 - -/** \brief Identifier for named curve sect283k1. */ -#define BR_EC_sect283k1 9 - -/** \brief Identifier for named curve sect283r1. */ -#define BR_EC_sect283r1 10 - -/** \brief Identifier for named curve sect409k1. */ -#define BR_EC_sect409k1 11 - -/** \brief Identifier for named curve sect409r1. */ -#define BR_EC_sect409r1 12 - -/** \brief Identifier for named curve sect571k1. */ -#define BR_EC_sect571k1 13 - -/** \brief Identifier for named curve sect571r1. */ -#define BR_EC_sect571r1 14 - -/** \brief Identifier for named curve secp160k1. */ -#define BR_EC_secp160k1 15 - -/** \brief Identifier for named curve secp160r1. */ -#define BR_EC_secp160r1 16 - -/** \brief Identifier for named curve secp160r2. */ -#define BR_EC_secp160r2 17 - -/** \brief Identifier for named curve secp192k1. */ -#define BR_EC_secp192k1 18 - -/** \brief Identifier for named curve secp192r1. */ -#define BR_EC_secp192r1 19 - -/** \brief Identifier for named curve secp224k1. */ -#define BR_EC_secp224k1 20 - -/** \brief Identifier for named curve secp224r1. */ -#define BR_EC_secp224r1 21 - -/** \brief Identifier for named curve secp256k1. */ -#define BR_EC_secp256k1 22 - -/** \brief Identifier for named curve secp256r1. */ -#define BR_EC_secp256r1 23 - -/** \brief Identifier for named curve secp384r1. */ -#define BR_EC_secp384r1 24 - -/** \brief Identifier for named curve secp521r1. */ -#define BR_EC_secp521r1 25 - -/** \brief Identifier for named curve brainpoolP256r1. */ -#define BR_EC_brainpoolP256r1 26 - -/** \brief Identifier for named curve brainpoolP384r1. */ -#define BR_EC_brainpoolP384r1 27 - -/** \brief Identifier for named curve brainpoolP512r1. */ -#define BR_EC_brainpoolP512r1 28 - -/** \brief Identifier for named curve Curve25519. */ -#define BR_EC_curve25519 29 - -/** \brief Identifier for named curve Curve448. */ -#define BR_EC_curve448 30 - -/** - * \brief Structure for an EC public key. - */ -typedef struct { - /** \brief Identifier for the curve used by this key. */ - int curve; - /** \brief Public curve point (uncompressed format). */ - unsigned char *q; - /** \brief Length of public curve point (in bytes). */ - size_t qlen; -} br_ec_public_key; - -/** - * \brief Structure for an EC private key. - * - * The private key is an integer modulo the curve subgroup order. The - * encoding below tolerates extra leading zeros. In general, it is - * recommended that the private key has the same length as the curve - * subgroup order. - */ -typedef struct { - /** \brief Identifier for the curve used by this key. */ - int curve; - /** \brief Private key (integer, unsigned big-endian encoding). */ - unsigned char *x; - /** \brief Private key length (in bytes). */ - size_t xlen; -} br_ec_private_key; - -/** - * \brief Type for an EC implementation. - */ -typedef struct { - /** - * \brief Supported curves. - * - * This word is a bitfield: bit `x` is set if the curve of ID `x` - * is supported. E.g. an implementation supporting both NIST P-256 - * (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have - * value `0x01800000` in this field. - */ - uint32_t supported_curves; - - /** - * \brief Get the conventional generator. - * - * This function returns the conventional generator (encoded - * curve point) for the specified curve. This function MUST NOT - * be called if the curve is not supported. - * - * \param curve curve identifier. - * \param len receiver for the encoded generator length (in bytes). - * \return the encoded generator. - */ - const unsigned char *(*generator)(int curve, size_t *len); - - /** - * \brief Get the subgroup order. - * - * This function returns the order of the subgroup generated by - * the conventional generator, for the specified curve. Unsigned - * big-endian encoding is used. This function MUST NOT be called - * if the curve is not supported. - * - * \param curve curve identifier. - * \param len receiver for the encoded order length (in bytes). - * \return the encoded order. - */ - const unsigned char *(*order)(int curve, size_t *len); - - /** - * \brief Get the offset and length for the X coordinate. - * - * This function returns the offset and length (in bytes) of - * the X coordinate in an encoded non-zero point. - * - * \param curve curve identifier. - * \param len receiver for the X coordinate length (in bytes). - * \return the offset for the X coordinate (in bytes). - */ - size_t (*xoff)(int curve, size_t *len); - - /** - * \brief Multiply a curve point by an integer. - * - * The source point is provided in array `G` (of size `Glen` bytes); - * the multiplication result is written over it. The multiplier - * `x` (of size `xlen` bytes) uses unsigned big-endian encoding. - * - * Rules: - * - * - The specified curve MUST be supported. - * - * - The source point must be a valid point on the relevant curve - * subgroup (and not the "point at infinity" either). If this is - * not the case, then this function returns an error (0). - * - * - The multiplier integer MUST be non-zero and less than the - * curve subgroup order. If this property does not hold, then - * the result is indeterminate and an error code is not - * guaranteed. - * - * Returned value is 1 on success, 0 on error. On error, the - * contents of `G` are indeterminate. - * - * \param G point to multiply. - * \param Glen length of the encoded point (in bytes). - * \param x multiplier (unsigned big-endian). - * \param xlen multiplier length (in bytes). - * \param curve curve identifier. - * \return 1 on success, 0 on error. - */ - uint32_t (*mul)(unsigned char *G, size_t Glen, - const unsigned char *x, size_t xlen, int curve); - - /** - * \brief Multiply the generator by an integer. - * - * The multiplier MUST be non-zero and less than the curve - * subgroup order. Results are indeterminate if this property - * does not hold. - * - * \param R output buffer for the point. - * \param x multiplier (unsigned big-endian). - * \param xlen multiplier length (in bytes). - * \param curve curve identifier. - * \return encoded result point length (in bytes). - */ - size_t (*mulgen)(unsigned char *R, - const unsigned char *x, size_t xlen, int curve); - - /** - * \brief Multiply two points by two integers and add the - * results. - * - * The point `x*A + y*B` is computed and written back in the `A` - * array. - * - * Rules: - * - * - The specified curve MUST be supported. - * - * - The source points (`A` and `B`) must be valid points on - * the relevant curve subgroup (and not the "point at - * infinity" either). If this is not the case, then this - * function returns an error (0). - * - * - If the `B` pointer is `NULL`, then the conventional - * subgroup generator is used. With some implementations, - * this may be faster than providing a pointer to the - * generator. - * - * - The multiplier integers (`x` and `y`) MUST be non-zero - * and less than the curve subgroup order. If either integer - * is zero, then an error is reported, but if one of them is - * not lower than the subgroup order, then the result is - * indeterminate and an error code is not guaranteed. - * - * - If the final result is the point at infinity, then an - * error is returned. - * - * Returned value is 1 on success, 0 on error. On error, the - * contents of `A` are indeterminate. - * - * \param A first point to multiply. - * \param B second point to multiply (`NULL` for the generator). - * \param len common length of the encoded points (in bytes). - * \param x multiplier for `A` (unsigned big-endian). - * \param xlen length of multiplier for `A` (in bytes). - * \param y multiplier for `A` (unsigned big-endian). - * \param ylen length of multiplier for `A` (in bytes). - * \param curve curve identifier. - * \return 1 on success, 0 on error. - */ - uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve); -} br_ec_impl; - -/** - * \brief EC implementation "i31". - * - * This implementation internally uses generic code for modular integers, - * with a representation as sequences of 31-bit words. It supports secp256r1, - * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). - */ -extern const br_ec_impl br_ec_prime_i31; - -/** - * \brief EC implementation "i15". - * - * This implementation internally uses generic code for modular integers, - * with a representation as sequences of 15-bit words. It supports secp256r1, - * secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521). - */ -extern const br_ec_impl br_ec_prime_i15; - -/** - * \brief EC implementation "m15" for P-256. - * - * This implementation uses specialised code for curve secp256r1 (also - * known as NIST P-256), with optional Karatsuba decomposition, and fast - * modular reduction thanks to the field modulus special format. Only - * 32-bit multiplications are used (with 32-bit results, not 64-bit). - */ -extern const br_ec_impl br_ec_p256_m15; - -/** - * \brief EC implementation "m31" for P-256. - * - * This implementation uses specialised code for curve secp256r1 (also - * known as NIST P-256), relying on multiplications of 31-bit values - * (MUL31). - */ -extern const br_ec_impl br_ec_p256_m31; - -/** - * \brief EC implementation "i15" (generic code) for Curve25519. - * - * This implementation uses the generic code for modular integers (with - * 15-bit words) to support Curve25519. Due to the specificities of the - * curve definition, the following applies: - * - * - `muladd()` is not implemented (the function returns 0 systematically). - * - `order()` returns 2^255-1, since the point multiplication algorithm - * accepts any 32-bit integer as input (it clears the top bit and low - * three bits systematically). - */ -extern const br_ec_impl br_ec_c25519_i15; - -/** - * \brief EC implementation "i31" (generic code) for Curve25519. - * - * This implementation uses the generic code for modular integers (with - * 31-bit words) to support Curve25519. Due to the specificities of the - * curve definition, the following applies: - * - * - `muladd()` is not implemented (the function returns 0 systematically). - * - `order()` returns 2^255-1, since the point multiplication algorithm - * accepts any 32-bit integer as input (it clears the top bit and low - * three bits systematically). - */ -extern const br_ec_impl br_ec_c25519_i31; - -/** - * \brief EC implementation "m15" (specialised code) for Curve25519. - * - * This implementation uses custom code relying on multiplication of - * integers up to 15 bits. Due to the specificities of the curve - * definition, the following applies: - * - * - `muladd()` is not implemented (the function returns 0 systematically). - * - `order()` returns 2^255-1, since the point multiplication algorithm - * accepts any 32-bit integer as input (it clears the top bit and low - * three bits systematically). - */ -extern const br_ec_impl br_ec_c25519_m15; - -/** - * \brief EC implementation "m31" (specialised code) for Curve25519. - * - * This implementation uses custom code relying on multiplication of - * integers up to 31 bits. Due to the specificities of the curve - * definition, the following applies: - * - * - `muladd()` is not implemented (the function returns 0 systematically). - * - `order()` returns 2^255-1, since the point multiplication algorithm - * accepts any 32-bit integer as input (it clears the top bit and low - * three bits systematically). - */ -extern const br_ec_impl br_ec_c25519_m31; - -/** - * \brief Aggregate EC implementation "m15". - * - * This implementation is a wrapper for: - * - * - `br_ec_c25519_m15` for Curve25519 - * - `br_ec_p256_m15` for NIST P-256 - * - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512) - */ -extern const br_ec_impl br_ec_all_m15; - -/** - * \brief Aggregate EC implementation "m31". - * - * This implementation is a wrapper for: - * - * - `br_ec_c25519_m31` for Curve25519 - * - `br_ec_p256_m31` for NIST P-256 - * - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512) - */ -extern const br_ec_impl br_ec_all_m31; - -/** - * \brief Get the "default" EC implementation for the current system. - * - * This returns a pointer to the preferred implementation on the - * current system. - * - * \return the default EC implementation. - */ -const br_ec_impl *br_ec_get_default(void); - -/** - * \brief Convert a signature from "raw" to "asn1". - * - * Conversion is done "in place" and the new length is returned. - * Conversion may enlarge the signature, but by no more than 9 bytes at - * most. On error, 0 is returned (error conditions include an odd raw - * signature length, or an oversized integer). - * - * \param sig signature to convert. - * \param sig_len signature length (in bytes). - * \return the new signature length, or 0 on error. - */ -size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len); - -/** - * \brief Convert a signature from "asn1" to "raw". - * - * Conversion is done "in place" and the new length is returned. - * Conversion may enlarge the signature, but the new signature length - * will be less than twice the source length at most. On error, 0 is - * returned (error conditions include an invalid ASN.1 structure or an - * oversized integer). - * - * \param sig signature to convert. - * \param sig_len signature length (in bytes). - * \return the new signature length, or 0 on error. - */ -size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len); - -/** - * \brief Type for an ECDSA signer function. - * - * A pointer to the EC implementation is provided. The hash value is - * assumed to have the length inferred from the designated hash function - * class. - * - * Signature is written in the buffer pointed to by `sig`, and the length - * (in bytes) is returned. On error, nothing is written in the buffer, - * and 0 is returned. This function returns 0 if the specified curve is - * not supported by the provided EC implementation. - * - * The signature format is either "raw" or "asn1", depending on the - * implementation; maximum length is predictable from the implemented - * curve: - * - * | curve | raw | asn1 | - * | :--------- | --: | ---: | - * | NIST P-256 | 64 | 72 | - * | NIST P-384 | 96 | 104 | - * | NIST P-521 | 132 | 139 | - * - * \param impl EC implementation to use. - * \param hf hash function used to process the data. - * \param hash_value signed data (hashed). - * \param sk EC private key. - * \param sig destination buffer. - * \return the signature length (in bytes), or 0 on error. - */ -typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -/** - * \brief Type for an ECDSA signature verification function. - * - * A pointer to the EC implementation is provided. The hashed value, - * computed over the purportedly signed data, is also provided with - * its length. - * - * The signature format is either "raw" or "asn1", depending on the - * implementation. - * - * Returned value is 1 on success (valid signature), 0 on error. This - * function returns 0 if the specified curve is not supported by the - * provided EC implementation. - * - * \param impl EC implementation to use. - * \param hash signed data (hashed). - * \param hash_len hash value length (in bytes). - * \param pk EC public key. - * \param sig signature. - * \param sig_len signature length (in bytes). - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, const void *sig, size_t sig_len); - -/** - * \brief ECDSA signature generator, "i31" implementation, "asn1" format. - * - * \see br_ecdsa_sign() - * - * \param impl EC implementation to use. - * \param hf hash function used to process the data. - * \param hash_value signed data (hashed). - * \param sk EC private key. - * \param sig destination buffer. - * \return the signature length (in bytes), or 0 on error. - */ -size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -/** - * \brief ECDSA signature generator, "i31" implementation, "raw" format. - * - * \see br_ecdsa_sign() - * - * \param impl EC implementation to use. - * \param hf hash function used to process the data. - * \param hash_value signed data (hashed). - * \param sk EC private key. - * \param sig destination buffer. - * \return the signature length (in bytes), or 0 on error. - */ -size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -/** - * \brief ECDSA signature verifier, "i31" implementation, "asn1" format. - * - * \see br_ecdsa_vrfy() - * - * \param impl EC implementation to use. - * \param hash signed data (hashed). - * \param hash_len hash value length (in bytes). - * \param pk EC public key. - * \param sig signature. - * \param sig_len signature length (in bytes). - * \return 1 on success, 0 on error. - */ -uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, const void *sig, size_t sig_len); - -/** - * \brief ECDSA signature verifier, "i31" implementation, "raw" format. - * - * \see br_ecdsa_vrfy() - * - * \param impl EC implementation to use. - * \param hash signed data (hashed). - * \param hash_len hash value length (in bytes). - * \param pk EC public key. - * \param sig signature. - * \param sig_len signature length (in bytes). - * \return 1 on success, 0 on error. - */ -uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, const void *sig, size_t sig_len); - -/** - * \brief ECDSA signature generator, "i15" implementation, "asn1" format. - * - * \see br_ecdsa_sign() - * - * \param impl EC implementation to use. - * \param hf hash function used to process the data. - * \param hash_value signed data (hashed). - * \param sk EC private key. - * \param sig destination buffer. - * \return the signature length (in bytes), or 0 on error. - */ -size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -/** - * \brief ECDSA signature generator, "i15" implementation, "raw" format. - * - * \see br_ecdsa_sign() - * - * \param impl EC implementation to use. - * \param hf hash function used to process the data. - * \param hash_value signed data (hashed). - * \param sk EC private key. - * \param sig destination buffer. - * \return the signature length (in bytes), or 0 on error. - */ -size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -/** - * \brief ECDSA signature verifier, "i15" implementation, "asn1" format. - * - * \see br_ecdsa_vrfy() - * - * \param impl EC implementation to use. - * \param hash signed data (hashed). - * \param hash_len hash value length (in bytes). - * \param pk EC public key. - * \param sig signature. - * \param sig_len signature length (in bytes). - * \return 1 on success, 0 on error. - */ -uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, const void *sig, size_t sig_len); - -/** - * \brief ECDSA signature verifier, "i15" implementation, "raw" format. - * - * \see br_ecdsa_vrfy() - * - * \param impl EC implementation to use. - * \param hash signed data (hashed). - * \param hash_len hash value length (in bytes). - * \param pk EC public key. - * \param sig signature. - * \param sig_len signature length (in bytes). - * \return 1 on success, 0 on error. - */ -uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, const void *sig, size_t sig_len); - -/** - * \brief Get "default" ECDSA implementation (signer, asn1 format). - * - * This returns the preferred implementation of ECDSA signature generation - * ("asn1" output format) on the current system. - * - * \return the default implementation. - */ -br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void); - -/** - * \brief Get "default" ECDSA implementation (signer, raw format). - * - * This returns the preferred implementation of ECDSA signature generation - * ("raw" output format) on the current system. - * - * \return the default implementation. - */ -br_ecdsa_sign br_ecdsa_sign_raw_get_default(void); - -/** - * \brief Get "default" ECDSA implementation (verifier, asn1 format). - * - * This returns the preferred implementation of ECDSA signature verification - * ("asn1" output format) on the current system. - * - * \return the default implementation. - */ -br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void); - -/** - * \brief Get "default" ECDSA implementation (verifier, raw format). - * - * This returns the preferred implementation of ECDSA signature verification - * ("raw" output format) on the current system. - * - * \return the default implementation. - */ -br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void); - -/** - * \brief Maximum size for EC private key element buffer. - * - * This is the largest number of bytes that `br_ec_keygen()` may need or - * ever return. - */ -#define BR_EC_KBUF_PRIV_MAX_SIZE 72 - -/** - * \brief Maximum size for EC public key element buffer. - * - * This is the largest number of bytes that `br_ec_compute_public()` may - * need or ever return. - */ -#define BR_EC_KBUF_PUB_MAX_SIZE 145 - -/** - * \brief Generate a new EC private key. - * - * If the specified `curve` is not supported by the elliptic curve - * implementation (`impl`), then this function returns zero. - * - * The `sk` structure fields are set to the new private key data. In - * particular, `sk.x` is made to point to the provided key buffer (`kbuf`), - * in which the actual private key data is written. That buffer is assumed - * to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum - * size for all supported curves. - * - * The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then - * the private key is not actually generated, and `sk` may also be `NULL`; - * the minimum length for `kbuf` is still computed and returned. - * - * If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is - * still generated and stored in `kbuf`. - * - * \param rng_ctx source PRNG context (already initialized). - * \param impl the elliptic curve implementation. - * \param sk the private key structure to fill, or `NULL`. - * \param kbuf the key element buffer, or `NULL`. - * \param curve the curve identifier. - * \return the key data length (in bytes), or zero. - */ -size_t br_ec_keygen(const br_prng_class **rng_ctx, - const br_ec_impl *impl, br_ec_private_key *sk, - void *kbuf, int curve); - -/** - * \brief Compute EC public key from EC private key. - * - * This function uses the provided elliptic curve implementation (`impl`) - * to compute the public key corresponding to the private key held in `sk`. - * The public key point is written into `kbuf`, which is then linked from - * the `*pk` structure. The size of the public key point, i.e. the number - * of bytes used in `kbuf`, is returned. - * - * If `kbuf` is `NULL`, then the public key point is NOT computed, and - * the public key structure `*pk` is unmodified (`pk` may be `NULL` in - * that case). The size of the public key point is still returned. - * - * If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key - * point is computed and stored in `kbuf`, and its size is returned. - * - * If the curve used by the private key is not supported by the curve - * implementation, then this function returns zero. - * - * The private key MUST be valid. An off-range private key value is not - * necessarily detected, and leads to unpredictable results. - * - * \param impl the elliptic curve implementation. - * \param pk the public key structure to fill (or `NULL`). - * \param kbuf the public key point buffer (or `NULL`). - * \param sk the source private key. - * \return the public key point length (in bytes), or zero. - */ -size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, - void *kbuf, const br_ec_private_key *sk); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_hash.h b/src/tls/bearssl/bearssl_hash.h deleted file mode 100644 index 3b15ba7ca..000000000 --- a/src/tls/bearssl/bearssl_hash.h +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_HASH_H__ -#define BR_BEARSSL_HASH_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_hash.h - * - * # Hash Functions - * - * This file documents the API for hash functions. - * - * - * ## Procedural API - * - * For each implemented hash function, of name "`xxx`", the following - * elements are defined: - * - * - `br_xxx_vtable` - * - * An externally defined instance of `br_hash_class`. - * - * - `br_xxx_SIZE` - * - * A macro that evaluates to the output size (in bytes) of the - * hash function. - * - * - `br_xxx_ID` - * - * A macro that evaluates to a symbolic identifier for the hash - * function. Such identifiers are used with HMAC and signature - * algorithm implementations. - * - * NOTE: for the "standard" hash functions defined in [the TLS - * standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1), - * the symbolic identifiers match the constants used in TLS, i.e. - * 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512, - * respectively. - * - * - `br_xxx_context` - * - * Context for an ongoing computation. It is allocated by the - * caller, and a pointer to it is passed to all functions. A - * context contains no interior pointer, so it can be moved around - * and cloned (with a simple `memcpy()` or equivalent) in order to - * capture the function state at some point. Computations that use - * distinct context structures are independent of each other. The - * first field of `br_xxx_context` is always a pointer to the - * `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer. - * - * - `br_xxx_init(br_xxx_context *ctx)` - * - * Initialise the provided context. Previous contents of the structure - * are ignored. This calls resets the context to the start of a new - * hash computation; it also sets the first field of the context - * structure (called `vtable`) to a pointer to the statically - * allocated constant `br_xxx_vtable` structure. - * - * - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)` - * - * Add some more bytes to the hash computation represented by the - * provided context. - * - * - `br_xxx_out(const br_xxx_context *ctx, void *out)` - * - * Complete the hash computation and write the result in the provided - * buffer. The output buffer MUST be large enough to accommodate the - * result. The context is NOT modified by this operation, so this - * function can be used to get a "partial hash" while still keeping - * the possibility of adding more bytes to the input. - * - * - `br_xxx_state(const br_xxx_context *ctx, void *out)` - * - * Get a copy of the "current state" for the computation so far. For - * MD functions (MD5, SHA-1, SHA-2 family), this is the running state - * resulting from the processing of the last complete input block. - * Returned value is the current input length (in bytes). - * - * - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)` - * - * Set the internal state to the provided values. The 'stb' and - * 'count' values shall match that which was obtained from - * `br_xxx_state()`. This restores the hash state only if the state - * values were at an appropriate block boundary. This does NOT set - * the `vtable` pointer in the context. - * - * Context structures can be discarded without any explicit deallocation. - * Hash function implementations are purely software and don't reserve - * any resources outside of the context structure itself. - * - * - * ## Object-Oriented API - * - * For each hash function that follows the procedural API described - * above, an object-oriented API is also provided. In that API, function - * pointers from the vtable (`br_xxx_vtable`) are used. The vtable - * incarnates object-oriented programming. An introduction on the OOP - * concept used here can be read on the BearSSL Web site:
- *    [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) - * - * The vtable offers functions called `init()`, `update()`, `out()`, - * `set()` and `set_state()`, which are in fact the functions from - * the procedural API. That vtable also contains two informative fields: - * - * - `context_size` - * - * The size of the context structure (`br_xxx_context`), in bytes. - * This can be used by generic implementations to perform dynamic - * context allocation. - * - * - `desc` - * - * A "descriptor" field that encodes some information on the hash - * function: symbolic identifier, output size, state size, - * internal block size, details on the padding. - * - * Users of this object-oriented API (in particular generic HMAC - * implementations) may make the following assumptions: - * - * - Hash output size is no more than 64 bytes. - * - Hash internal state size is no more than 64 bytes. - * - Internal block size is a power of two, no less than 16 and no more - * than 256. - * - * - * ## Implemented Hash Functions - * - * Implemented hash functions are: - * - * | Function | Name | Output length | State length | - * | :-------- | :------ | :-----------: | :----------: | - * | MD5 | md5 | 16 | 16 | - * | SHA-1 | sha1 | 20 | 20 | - * | SHA-224 | sha224 | 28 | 32 | - * | SHA-256 | sha256 | 32 | 32 | - * | SHA-384 | sha384 | 48 | 64 | - * | SHA-512 | sha512 | 64 | 64 | - * | MD5+SHA-1 | md5sha1 | 36 | 36 | - * - * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the - * same input; in the implementation, the internal data buffer is - * shared, thus making it more memory-efficient than separate MD5 and - * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS - * 1.1.) - * - * - * ## Multi-Hasher - * - * An aggregate hasher is provided, that can compute several standard - * hash functions in parallel. It uses `br_multihash_context` and a - * procedural API. It is configured with the implementations (the vtables) - * that it should use; it will then compute all these hash functions in - * parallel, on the same input. It is meant to be used in cases when the - * hash of an object will be used, but the exact hash function is not - * known yet (typically, streamed processing on X.509 certificates). - * - * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 - * and SHA-512) are supported by the multi-hasher. - * - * - * ## GHASH - * - * GHASH is not a generic hash function; it is a _universal_ hash function, - * which, as the name does not say, means that it CANNOT be used in most - * places where a hash function is needed. GHASH is used within the GCM - * encryption mode, to provide the checked integrity functionality. - * - * A GHASH implementation is basically a function that uses the type defined - * in this file under the name `br_ghash`: - * - * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); - * - * The `y` pointer refers to a 16-byte value which is used as input, and - * receives the output of the GHASH invocation. `h` is a 16-byte secret - * value (that serves as key). `data` and `len` define the input data. - * - * Three GHASH implementations are provided, all constant-time, based on - * the use of integer multiplications with appropriate masking to cancel - * carry propagation. - */ - -/** - * \brief Class type for hash function implementations. - * - * A `br_hash_class` instance references the methods implementing a hash - * function. Constant instances of this structure are defined for each - * implemented hash function. Such instances are also called "vtables". - * - * Vtables are used to support object-oriented programming, as - * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). - */ -typedef struct br_hash_class_ br_hash_class; -struct br_hash_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate for - * computing this hash function. - */ - size_t context_size; - - /** - * \brief Descriptor word that contains information about the hash - * function. - * - * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` - * and `BR_HASHDESC_xxx_MASK` to access the specific value, as - * follows: - * - * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK - * - * The defined elements are: - * - * - `ID`: the symbolic identifier for the function, as defined - * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) - * (MD5 = 1, SHA-1 = 2,...). - * - * - `OUT`: hash output size, in bytes. - * - * - `STATE`: internal running state size, in bytes. - * - * - `LBLEN`: base-2 logarithm for the internal block size, as - * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 - * and SHA-256, since these functions use 64-byte blocks; for - * SHA-384 and SHA-512, this is 7, corresponding to their - * 128-byte blocks). - * - * The descriptor may contain a few other flags. - */ - uint32_t desc; - - /** - * \brief Initialisation method. - * - * This method takes as parameter a pointer to a context area, - * that it initialises. The first field of the context is set - * to this vtable; other elements are initialised for a new hash - * computation. - * - * \param ctx pointer to (the first field of) the context. - */ - void (*init)(const br_hash_class **ctx); - - /** - * \brief Data injection method. - * - * The `len` bytes starting at address `data` are injected into - * the running hash computation incarnated by the specified - * context. The context is updated accordingly. It is allowed - * to have `len == 0`, in which case `data` is ignored (and could - * be `NULL`), and nothing happens. - * on the input data. - * - * \param ctx pointer to (the first field of) the context. - * \param data pointer to the first data byte to inject. - * \param len number of bytes to inject. - */ - void (*update)(const br_hash_class **ctx, const void *data, size_t len); - - /** - * \brief Produce hash output. - * - * The hash output corresponding to all data bytes injected in the - * context since the last `init()` call is computed, and written - * in the buffer pointed to by `dst`. The hash output size depends - * on the implemented hash function (e.g. 16 bytes for MD5). - * The context is _not_ modified by this call, so further bytes - * may be afterwards injected to continue the current computation. - * - * \param ctx pointer to (the first field of) the context. - * \param dst destination buffer for the hash output. - */ - void (*out)(const br_hash_class *const *ctx, void *dst); - - /** - * \brief Get running state. - * - * This method saves the current running state into the `dst` - * buffer. What constitutes the "running state" depends on the - * hash function; for Merkle-DamgÃ¥rd hash functions (like - * MD5 or SHA-1), this is the output obtained after processing - * each block. The number of bytes injected so far is returned. - * The context is not modified by this call. - * - * \param ctx pointer to (the first field of) the context. - * \param dst destination buffer for the state. - * \return the injected total byte length. - */ - uint64_t (*state)(const br_hash_class *const *ctx, void *dst); - - /** - * \brief Set running state. - * - * This methods replaces the running state for the function. - * - * \param ctx pointer to (the first field of) the context. - * \param stb source buffer for the state. - * \param count injected total byte length. - */ - void (*set_state)(const br_hash_class **ctx, - const void *stb, uint64_t count); -}; - -#ifndef BR_DOXYGEN_IGNORE -#define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) -#define BR_HASHDESC_ID_OFF 0 -#define BR_HASHDESC_ID_MASK 0xFF - -#define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) -#define BR_HASHDESC_OUT_OFF 8 -#define BR_HASHDESC_OUT_MASK 0x7F - -#define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) -#define BR_HASHDESC_STATE_OFF 15 -#define BR_HASHDESC_STATE_MASK 0xFF - -#define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) -#define BR_HASHDESC_LBLEN_OFF 23 -#define BR_HASHDESC_LBLEN_MASK 0x0F - -#define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) -#define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) -#define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) -#endif - -/* - * Specific hash functions. - * - * Rules for contexts: - * -- No interior pointer. - * -- No pointer to external dynamically allocated resources. - * -- First field is called 'vtable' and is a pointer to a - * const-qualified br_hash_class instance (pointer is set by init()). - * -- SHA-224 and SHA-256 contexts are identical. - * -- SHA-384 and SHA-512 contexts are identical. - * - * Thus, contexts can be moved and cloned to capture the hash function - * current state; and there is no need for any explicit "release" function. - */ - -/** - * \brief Symbolic identifier for MD5. - */ -#define br_md5_ID 1 - -/** - * \brief MD5 output size (in bytes). - */ -#define br_md5_SIZE 16 - -/** - * \brief Constant vtable for MD5. - */ -extern const br_hash_class br_md5_vtable; - -/** - * \brief MD5 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[64]; - uint64_t count; - uint32_t val[4]; -#endif -} br_md5_context; - -/** - * \brief MD5 context initialisation. - * - * This function initialises or resets a context for a new MD5 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_md5_init(br_md5_context *ctx); - -/** - * \brief Inject some data bytes in a running MD5 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_md5_update(br_md5_context *ctx, const void *data, size_t len); - -/** - * \brief Compute MD5 output. - * - * The MD5 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_md5_out(const br_md5_context *ctx, void *out); - -/** - * \brief Save MD5 running state. - * - * The running state for MD5 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_md5_state(const br_md5_context *ctx, void *out); - -/** - * \brief Restore MD5 running state. - * - * The running state for MD5 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); - -/** - * \brief Symbolic identifier for SHA-1. - */ -#define br_sha1_ID 2 - -/** - * \brief SHA-1 output size (in bytes). - */ -#define br_sha1_SIZE 20 - -/** - * \brief Constant vtable for SHA-1. - */ -extern const br_hash_class br_sha1_vtable; - -/** - * \brief SHA-1 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[64]; - uint64_t count; - uint32_t val[5]; -#endif -} br_sha1_context; - -/** - * \brief SHA-1 context initialisation. - * - * This function initialises or resets a context for a new SHA-1 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_sha1_init(br_sha1_context *ctx); - -/** - * \brief Inject some data bytes in a running SHA-1 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); - -/** - * \brief Compute SHA-1 output. - * - * The SHA-1 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_sha1_out(const br_sha1_context *ctx, void *out); - -/** - * \brief Save SHA-1 running state. - * - * The running state for SHA-1 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); - -/** - * \brief Restore SHA-1 running state. - * - * The running state for SHA-1 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); - -/** - * \brief Symbolic identifier for SHA-224. - */ -#define br_sha224_ID 3 - -/** - * \brief SHA-224 output size (in bytes). - */ -#define br_sha224_SIZE 28 - -/** - * \brief Constant vtable for SHA-224. - */ -extern const br_hash_class br_sha224_vtable; - -/** - * \brief SHA-224 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[64]; - uint64_t count; - uint32_t val[8]; -#endif -} br_sha224_context; - -/** - * \brief SHA-224 context initialisation. - * - * This function initialises or resets a context for a new SHA-224 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_sha224_init(br_sha224_context *ctx); - -/** - * \brief Inject some data bytes in a running SHA-224 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); - -/** - * \brief Compute SHA-224 output. - * - * The SHA-224 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_sha224_out(const br_sha224_context *ctx, void *out); - -/** - * \brief Save SHA-224 running state. - * - * The running state for SHA-224 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); - -/** - * \brief Restore SHA-224 running state. - * - * The running state for SHA-224 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_sha224_set_state(br_sha224_context *ctx, - const void *stb, uint64_t count); - -/** - * \brief Symbolic identifier for SHA-256. - */ -#define br_sha256_ID 4 - -/** - * \brief SHA-256 output size (in bytes). - */ -#define br_sha256_SIZE 32 - -/** - * \brief Constant vtable for SHA-256. - */ -extern const br_hash_class br_sha256_vtable; - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief SHA-256 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -} br_sha256_context; -#else -typedef br_sha224_context br_sha256_context; -#endif - -/** - * \brief SHA-256 context initialisation. - * - * This function initialises or resets a context for a new SHA-256 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_sha256_init(br_sha256_context *ctx); - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief Inject some data bytes in a running SHA-256 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); -#else -#define br_sha256_update br_sha224_update -#endif - -/** - * \brief Compute SHA-256 output. - * - * The SHA-256 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_sha256_out(const br_sha256_context *ctx, void *out); - -#if BR_DOXYGEN_IGNORE -/** - * \brief Save SHA-256 running state. - * - * The running state for SHA-256 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); -#else -#define br_sha256_state br_sha224_state -#endif - -#if BR_DOXYGEN_IGNORE -/** - * \brief Restore SHA-256 running state. - * - * The running state for SHA-256 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_sha256_set_state(br_sha256_context *ctx, - const void *stb, uint64_t count); -#else -#define br_sha256_set_state br_sha224_set_state -#endif - -/** - * \brief Symbolic identifier for SHA-384. - */ -#define br_sha384_ID 5 - -/** - * \brief SHA-384 output size (in bytes). - */ -#define br_sha384_SIZE 48 - -/** - * \brief Constant vtable for SHA-384. - */ -extern const br_hash_class br_sha384_vtable; - -/** - * \brief SHA-384 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[128]; - uint64_t count; - uint64_t val[8]; -#endif -} br_sha384_context; - -/** - * \brief SHA-384 context initialisation. - * - * This function initialises or resets a context for a new SHA-384 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_sha384_init(br_sha384_context *ctx); - -/** - * \brief Inject some data bytes in a running SHA-384 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); - -/** - * \brief Compute SHA-384 output. - * - * The SHA-384 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_sha384_out(const br_sha384_context *ctx, void *out); - -/** - * \brief Save SHA-384 running state. - * - * The running state for SHA-384 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); - -/** - * \brief Restore SHA-384 running state. - * - * The running state for SHA-384 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_sha384_set_state(br_sha384_context *ctx, - const void *stb, uint64_t count); - -/** - * \brief Symbolic identifier for SHA-512. - */ -#define br_sha512_ID 6 - -/** - * \brief SHA-512 output size (in bytes). - */ -#define br_sha512_SIZE 64 - -/** - * \brief Constant vtable for SHA-512. - */ -extern const br_hash_class br_sha512_vtable; - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief SHA-512 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -} br_sha512_context; -#else -typedef br_sha384_context br_sha512_context; -#endif - -/** - * \brief SHA-512 context initialisation. - * - * This function initialises or resets a context for a new SHA-512 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_sha512_init(br_sha512_context *ctx); - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief Inject some data bytes in a running SHA-512 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); -#else -#define br_sha512_update br_sha384_update -#endif - -/** - * \brief Compute SHA-512 output. - * - * The SHA-512 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_sha512_out(const br_sha512_context *ctx, void *out); - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief Save SHA-512 running state. - * - * The running state for SHA-512 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); -#else -#define br_sha512_state br_sha384_state -#endif - -#ifdef BR_DOXYGEN_IGNORE -/** - * \brief Restore SHA-512 running state. - * - * The running state for SHA-512 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_sha512_set_state(br_sha512_context *ctx, - const void *stb, uint64_t count); -#else -#define br_sha512_set_state br_sha384_set_state -#endif - -/* - * "md5sha1" is a special hash function that computes both MD5 and SHA-1 - * on the same input, and produces a 36-byte output (MD5 and SHA-1 - * concatenation, in that order). State size is also 36 bytes. - */ - -/** - * \brief Symbolic identifier for MD5+SHA-1. - * - * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the - * same input. It is not one of the functions identified in TLS, so - * we give it a symbolic identifier of value 0. - */ -#define br_md5sha1_ID 0 - -/** - * \brief MD5+SHA-1 output size (in bytes). - */ -#define br_md5sha1_SIZE 36 - -/** - * \brief Constant vtable for MD5+SHA-1. - */ -extern const br_hash_class br_md5sha1_vtable; - -/** - * \brief MD5+SHA-1 context. - * - * First field is a pointer to the vtable; it is set by the initialisation - * function. Other fields are not supposed to be accessed by user code. - */ -typedef struct { - /** - * \brief Pointer to vtable for this context. - */ - const br_hash_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[64]; - uint64_t count; - uint32_t val_md5[4]; - uint32_t val_sha1[5]; -#endif -} br_md5sha1_context; - -/** - * \brief MD5+SHA-1 context initialisation. - * - * This function initialises or resets a context for a new SHA-512 - * computation. It also sets the vtable pointer. - * - * \param ctx pointer to the context structure. - */ -void br_md5sha1_init(br_md5sha1_context *ctx); - -/** - * \brief Inject some data bytes in a running MD5+SHA-1 computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); - -/** - * \brief Compute MD5+SHA-1 output. - * - * The MD5+SHA-1 output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `out`. The context - * itself is not modified, so extra bytes may be injected afterwards - * to continue that computation. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the hash output. - */ -void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); - -/** - * \brief Save MD5+SHA-1 running state. - * - * The running state for MD5+SHA-1 (output of the last internal block - * processing) is written in the buffer pointed to by `out`. The - * number of bytes injected since the last initialisation or reset - * call is returned. The context is not modified. - * - * \param ctx pointer to the context structure. - * \param out destination buffer for the running state. - * \return the injected total byte length. - */ -uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); - -/** - * \brief Restore MD5+SHA-1 running state. - * - * The running state for MD5+SHA-1 is set to the provided values. - * - * \param ctx pointer to the context structure. - * \param stb source buffer for the running state. - * \param count the injected total byte length. - */ -void br_md5sha1_set_state(br_md5sha1_context *ctx, - const void *stb, uint64_t count); - -/** - * \brief Aggregate context for configurable hash function support. - * - * The `br_hash_compat_context` type is a type which is large enough to - * serve as context for all standard hash functions defined above. - */ -typedef union { - const br_hash_class *vtable; - br_md5_context md5; - br_sha1_context sha1; - br_sha224_context sha224; - br_sha256_context sha256; - br_sha384_context sha384; - br_sha512_context sha512; - br_md5sha1_context md5sha1; -} br_hash_compat_context; - -/* - * The multi-hasher is a construct that handles hashing of the same input - * data with several hash functions, with a single shared input buffer. - * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 - * simultaneously, though which functions are activated depends on - * the set implementation pointers. - */ - -/** - * \brief Multi-hasher context structure. - * - * The multi-hasher runs up to six hash functions in the standard TLS list - * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over - * the same input. - * - * The multi-hasher does _not_ follow the OOP structure with a vtable. - * Instead, it is configured with the vtables of the hash functions it - * should run. Structure fields are not supposed to be accessed directly. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - unsigned char buf[128]; - uint64_t count; - uint32_t val_32[25]; - uint64_t val_64[16]; - const br_hash_class *impl[6]; -#endif -} br_multihash_context; - -/** - * \brief Clear a multi-hasher context. - * - * This should always be called once on a given context, _before_ setting - * the implementation pointers. - * - * \param ctx the multi-hasher context. - */ -void br_multihash_zero(br_multihash_context *ctx); - -/** - * \brief Set a hash function implementation. - * - * Implementations shall be set _after_ clearing the context (with - * `br_multihash_zero()`) but _before_ initialising the computation - * (with `br_multihash_init()`). The hash function implementation - * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, - * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove - * an implementation from the multi-hasher. - * - * \param ctx the multi-hasher context. - * \param id the hash function symbolic identifier. - * \param impl the hash function vtable, or `NULL`. - */ -static inline void -br_multihash_setimpl(br_multihash_context *ctx, - int id, const br_hash_class *impl) -{ - /* - * This code relies on hash functions ID being values 1 to 6, - * in the MD5 to SHA-512 order. - */ - ctx->impl[id - 1] = impl; -} - -/** - * \brief Get a hash function implementation. - * - * This function returns the currently configured vtable for a given - * hash function (by symbolic ID). If no such function was configured in - * the provided multi-hasher context, then this function returns `NULL`. - * - * \param ctx the multi-hasher context. - * \param id the hash function symbolic identifier. - * \return the hash function vtable, or `NULL`. - */ -static inline const br_hash_class * -br_multihash_getimpl(const br_multihash_context *ctx, int id) -{ - return ctx->impl[id - 1]; -} - -/** - * \brief Reset a multi-hasher context. - * - * This function prepares the context for a new hashing computation, - * for all implementations configured at that point. - * - * \param ctx the multi-hasher context. - */ -void br_multihash_init(br_multihash_context *ctx); - -/** - * \brief Inject some data bytes in a running multi-hashing computation. - * - * The provided context is updated with some data bytes. If the number - * of bytes (`len`) is zero, then the data pointer (`data`) is ignored - * and may be `NULL`, and this function does nothing. - * - * \param ctx pointer to the context structure. - * \param data pointer to the injected data. - * \param len injected data length (in bytes). - */ -void br_multihash_update(br_multihash_context *ctx, - const void *data, size_t len); - -/** - * \brief Compute a hash output from a multi-hasher. - * - * The hash output for the concatenation of all bytes injected in the - * provided context since the last initialisation or reset call, is - * computed and written in the buffer pointed to by `dst`. The hash - * function to use is identified by `id` and must be one of the standard - * hash functions. If that hash function was indeed configured in the - * multi-hasher context, the corresponding hash value is written in - * `dst` and its length (in bytes) is returned. If the hash function - * was _not_ configured, then nothing is written in `dst` and 0 is - * returned. - * - * The context itself is not modified, so extra bytes may be injected - * afterwards to continue the hash computations. - * - * \param ctx pointer to the context structure. - * \param id the hash function symbolic identifier. - * \param dst destination buffer for the hash output. - * \return the hash output length (in bytes), or 0. - */ -size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); - -/** - * \brief Type for a GHASH implementation. - * - * GHASH is a sort of keyed hash meant to be used to implement GCM in - * combination with a block cipher (with 16-byte blocks). - * - * The `y` array has length 16 bytes and is used for input and output; in - * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte - * value that serves as key (it is derived from the encryption key in GCM, - * using the block cipher). The data length (`len`) is expressed in bytes. - * The `y` array is updated. - * - * If the data length is not a multiple of 16, then the data is implicitly - * padded with zeros up to the next multiple of 16. Thus, when using GHASH - * in GCM, this method may be called twice, for the associated data and - * for the ciphertext, respectively; the zero-padding implements exactly - * the GCM rules. - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); - -/** - * \brief GHASH implementation using multiplications (mixed 32-bit). - * - * This implementation uses multiplications of 32-bit values, with a - * 64-bit result. It is constant-time (if multiplications are - * constant-time). - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); - -/** - * \brief GHASH implementation using multiplications (strict 32-bit). - * - * This implementation uses multiplications of 32-bit values, with a - * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, - * but it is expected to be faster on architectures for which the - * 32-bit multiplication opcode does not yield the upper 32 bits of the - * product. It is constant-time (if multiplications are constant-time). - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); - -/** - * \brief GHASH implementation using multiplications (64-bit). - * - * This implementation uses multiplications of 64-bit values, with a - * 64-bit result. It is constant-time (if multiplications are - * constant-time). It is substantially faster than `br_ghash_ctmul()` - * and `br_ghash_ctmul32()` on most 64-bit architectures. - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); - -/** - * \brief GHASH implementation using the `pclmulqdq` opcode (part of the - * AES-NI instructions). - * - * This implementation is available only on x86 platforms where the - * compiler supports the relevant intrinsic functions. Even if the - * compiler supports these functions, the local CPU might not support - * the `pclmulqdq` opcode, meaning that a call will fail with an - * illegal instruction exception. To safely obtain a pointer to this - * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); - -/** - * \brief Obtain the `pclmul` GHASH implementation, if available. - * - * If the `pclmul` implementation was compiled in the library (depending - * on the compiler abilities) _and_ the local CPU appears to support the - * opcode, then this function will return a pointer to the - * `br_ghash_pclmul()` function. Otherwise, it will return `0`. - * - * \return the `pclmul` GHASH implementation, or `0`. - */ -br_ghash br_ghash_pclmul_get(void); - -/** - * \brief GHASH implementation using the POWER8 opcodes. - * - * This implementation is available only on POWER8 platforms (and later). - * To safely obtain a pointer to this function when supported (or 0 - * otherwise), use `br_ghash_pwr8_get()`. - * - * \param y the array to update. - * \param h the GHASH key. - * \param data the input data (may be `NULL` if `len` is zero). - * \param len the input data length (in bytes). - */ -void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); - -/** - * \brief Obtain the `pwr8` GHASH implementation, if available. - * - * If the `pwr8` implementation was compiled in the library (depending - * on the compiler abilities) _and_ the local CPU appears to support the - * opcode, then this function will return a pointer to the - * `br_ghash_pwr8()` function. Otherwise, it will return `0`. - * - * \return the `pwr8` GHASH implementation, or `0`. - */ -br_ghash br_ghash_pwr8_get(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_hmac.h b/src/tls/bearssl/bearssl_hmac.h deleted file mode 100644 index 4dc01ca31..000000000 --- a/src/tls/bearssl/bearssl_hmac.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_HMAC_H__ -#define BR_BEARSSL_HMAC_H__ - -#include -#include - -#include "bearssl_hash.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_hmac.h - * - * # HMAC - * - * HMAC is initialized with a key and an underlying hash function; it - * then fills a "key context". That context contains the processed - * key. - * - * With the key context, a HMAC context can be initialized to process - * the input bytes and obtain the MAC output. The key context is not - * modified during that process, and can be reused. - * - * IMPORTANT: HMAC shall be used only with functions that have the - * following properties: - * - * - hash output size does not exceed 64 bytes; - * - hash internal state size does not exceed 64 bytes; - * - internal block length is a power of 2 between 16 and 256 bytes. - */ - -/** - * \brief HMAC key context. - * - * The HMAC key context is initialised with a hash function implementation - * and a secret key. Contents are opaque (callers should not access them - * directly). The caller is responsible for allocating the context where - * appropriate. Context initialisation and usage incurs no dynamic - * allocation, so there is no release function. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - const br_hash_class *dig_vtable; - unsigned char ksi[64], kso[64]; -#endif -} br_hmac_key_context; - -/** - * \brief HMAC key context initialisation. - * - * Initialise the key context with the provided key, using the hash function - * identified by `digest_vtable`. This supports arbitrary key lengths. - * - * \param kc HMAC key context to initialise. - * \param digest_vtable pointer to the hash function implementation vtable. - * \param key pointer to the HMAC secret key. - * \param key_len HMAC secret key length (in bytes). - */ -void br_hmac_key_init(br_hmac_key_context *kc, - const br_hash_class *digest_vtable, const void *key, size_t key_len); - -/* - * \brief Get the underlying hash function. - * - * This function returns a pointer to the implementation vtable of the - * hash function used for this HMAC key context. - * - * \param kc HMAC key context. - * \return the hash function implementation. - */ -static inline const br_hash_class *br_hmac_key_get_digest( - const br_hmac_key_context *kc) -{ - return kc->dig_vtable; -} - -/** - * \brief HMAC computation context. - * - * The HMAC computation context maintains the state for a single HMAC - * computation. It is modified as input bytes are injected. The context - * is caller-allocated and has no release function since it does not - * dynamically allocate external resources. Its contents are opaque. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - br_hash_compat_context dig; - unsigned char kso[64]; - size_t out_len; -#endif -} br_hmac_context; - -/** - * \brief HMAC computation initialisation. - * - * Initialise a HMAC context with a key context. The key context is - * unmodified. Relevant data from the key context is immediately copied; - * the key context can thus be independently reused, modified or released - * without impacting this HMAC computation. - * - * An explicit output length can be specified; the actual output length - * will be the minimum of that value and the natural HMAC output length. - * If `out_len` is 0, then the natural HMAC output length is selected. The - * "natural output length" is the output length of the underlying hash - * function. - * - * \param ctx HMAC context to initialise. - * \param kc HMAC key context (already initialised with the key). - * \param out_len HMAC output length (0 to select "natural length"). - */ -void br_hmac_init(br_hmac_context *ctx, - const br_hmac_key_context *kc, size_t out_len); - -/** - * \brief Get the HMAC output size. - * - * The HMAC output size is the number of bytes that will actually be - * produced with `br_hmac_out()` with the provided context. This function - * MUST NOT be called on a non-initialised HMAC computation context. - * The returned value is the minimum of the HMAC natural length (output - * size of the underlying hash function) and the `out_len` parameter which - * was used with the last `br_hmac_init()` call on that context (if the - * initialisation `out_len` parameter was 0, then this function will - * return the HMAC natural length). - * - * \param ctx the (already initialised) HMAC computation context. - * \return the HMAC actual output size. - */ -static inline size_t -br_hmac_size(br_hmac_context *ctx) -{ - return ctx->out_len; -} - -/* - * \brief Get the underlying hash function. - * - * This function returns a pointer to the implementation vtable of the - * hash function used for this HMAC context. - * - * \param hc HMAC context. - * \return the hash function implementation. - */ -static inline const br_hash_class *br_hmac_get_digest( - const br_hmac_context *hc) -{ - return hc->dig.vtable; -} - -/** - * \brief Inject some bytes in HMAC. - * - * The provided `len` bytes are injected as extra input in the HMAC - * computation incarnated by the `ctx` HMAC context. It is acceptable - * that `len` is zero, in which case `data` is ignored (and may be - * `NULL`) and this function does nothing. - */ -void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); - -/** - * \brief Compute the HMAC output. - * - * The destination buffer MUST be large enough to accommodate the result; - * its length is at most the "natural length" of HMAC (i.e. the output - * length of the underlying hash function). The context is NOT modified; - * further bytes may be processed. Thus, "partial HMAC" values can be - * efficiently obtained. - * - * Returned value is the output length (in bytes). - * - * \param ctx HMAC computation context. - * \param out destination buffer for the HMAC output. - * \return the produced value length (in bytes). - */ -size_t br_hmac_out(const br_hmac_context *ctx, void *out); - -/** - * \brief Constant-time HMAC computation. - * - * This function compute the HMAC output in constant time. Some extra - * input bytes are processed, then the output is computed. The extra - * input consists in the `len` bytes pointed to by `data`. The `len` - * parameter must lie between `min_len` and `max_len` (inclusive); - * `max_len` bytes are actually read from `data`. Computing time (and - * memory access pattern) will not depend upon the data byte contents or - * the value of `len`. - * - * The output is written in the `out` buffer, that MUST be large enough - * to receive it. - * - * The difference `max_len - min_len` MUST be less than 230 - * (i.e. about one gigabyte). - * - * This function computes the output properly only if the underlying - * hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256, - * SHA-384 or SHA-512). - * - * The provided context is NOT modified. - * - * \param ctx the (already initialised) HMAC computation context. - * \param data the extra input bytes. - * \param len the extra input length (in bytes). - * \param min_len minimum extra input length (in bytes). - * \param max_len maximum extra input length (in bytes). - * \param out destination buffer for the HMAC output. - * \return the produced value length (in bytes). - */ -size_t br_hmac_outCT(const br_hmac_context *ctx, - const void *data, size_t len, size_t min_len, size_t max_len, - void *out); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_kdf.h b/src/tls/bearssl/bearssl_kdf.h deleted file mode 100644 index f018d7e8a..000000000 --- a/src/tls/bearssl/bearssl_kdf.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_KDF_H__ -#define BR_BEARSSL_KDF_H__ - -#include -#include - -#include "bearssl_hash.h" -#include "bearssl_hmac.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_kdf.h - * - * # Key Derivation Functions - * - * KDF are functions that takes a variable length input, and provide a - * variable length output, meant to be used to derive subkeys from a - * master key. - * - * ## HKDF - * - * HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869). - * It is based on HMAC, itself using an underlying hash function. Any - * hash function can be used, as long as it is compatible with the rules - * for the HMAC implementation (i.e. output size is 64 bytes or less, hash - * internal state size is 64 bytes or less, and the internal block length is - * a power of 2 between 16 and 256 bytes). HKDF has two phases: - * - * - HKDF-Extract: the input data in ingested, along with a "salt" value. - * - * - HKDF-Expand: the output is produced, from the result of processing - * the input and salt, and using an extra non-secret parameter called - * "info". - * - * The "salt" and "info" strings are non-secret and can be empty. Their role - * is normally to bind the input and output, respectively, to conventional - * identifiers that qualifu them within the used protocol or application. - * - * The implementation defined in this file uses the following functions: - * - * - `br_hkdf_init()`: initialize an HKDF context, with a hash function, - * and the salt. This starts the HKDF-Extract process. - * - * - `br_hkdf_inject()`: inject more input bytes. This function may be - * called repeatedly if the input data is provided by chunks. - * - * - `br_hkdf_flip()`: end the HKDF-Extract process, and start the - * HKDF-Expand process. - * - * - `br_hkdf_produce()`: get the next bytes of output. This function - * may be called several times to obtain the full output by chunks. - * For correct HKDF processing, the same "info" string must be - * provided for each call. - * - * Note that the HKDF total output size (the number of bytes that - * HKDF-Expand is willing to produce) is limited: if the hash output size - * is _n_ bytes, then the maximum output size is _255*n_. - */ - -/** - * \brief HKDF context. - * - * The HKDF context is initialized with a hash function implementation - * and a salt value. Contents are opaque (callers should not access them - * directly). The caller is responsible for allocating the context where - * appropriate. Context initialisation and usage incurs no dynamic - * allocation, so there is no release function. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - union { - br_hmac_context hmac_ctx; - br_hmac_key_context prk_ctx; - } u; - unsigned char buf[64]; - size_t ptr; - size_t dig_len; - unsigned chunk_num; -#endif -} br_hkdf_context; - -/** - * \brief HKDF context initialization. - * - * The underlying hash function and salt value are provided. Arbitrary - * salt lengths can be used. - * - * HKDF makes a difference between a salt of length zero, and an - * absent salt (the latter being equivalent to a salt consisting of - * bytes of value zero, of the same length as the hash function output). - * If `salt_len` is zero, then this function assumes that the salt is - * present but of length zero. To specify an _absent_ salt, use - * `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored). - * - * \param hc HKDF context to initialise. - * \param digest_vtable pointer to the hash function implementation vtable. - * \param salt HKDF-Extract salt. - * \param salt_len HKDF-Extract salt length (in bytes). - */ -void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, - const void *salt, size_t salt_len); - -/** - * \brief The special "absent salt" value for HKDF. - */ -#define BR_HKDF_NO_SALT (&br_hkdf_no_salt) - -#ifndef BR_DOXYGEN_IGNORE -extern const unsigned char br_hkdf_no_salt; -#endif - -/** - * \brief HKDF input injection (HKDF-Extract). - * - * This function injects some more input bytes ("key material") into - * HKDF. This function may be called several times, after `br_hkdf_init()` - * but before `br_hkdf_flip()`. - * - * \param hc HKDF context. - * \param ikm extra input bytes. - * \param ikm_len number of extra input bytes. - */ -void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len); - -/** - * \brief HKDF switch to the HKDF-Expand phase. - * - * This call terminates the HKDF-Extract process (input injection), and - * starts the HKDF-Expand process (output production). - * - * \param hc HKDF context. - */ -void br_hkdf_flip(br_hkdf_context *hc); - -/** - * \brief HKDF output production (HKDF-Expand). - * - * Produce more output bytes from the current state. This function may be - * called several times, but only after `br_hkdf_flip()`. - * - * Returned value is the number of actually produced bytes. The total - * output length is limited to 255 times the output length of the - * underlying hash function. - * - * \param hc HKDF context. - * \param info application specific information string. - * \param info_len application specific information string length (in bytes). - * \param out destination buffer for the HKDF output. - * \param out_len the length of the requested output (in bytes). - * \return the produced output length (in bytes). - */ -size_t br_hkdf_produce(br_hkdf_context *hc, - const void *info, size_t info_len, void *out, size_t out_len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_pem.h b/src/tls/bearssl/bearssl_pem.h deleted file mode 100644 index 8dba58272..000000000 --- a/src/tls/bearssl/bearssl_pem.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_PEM_H__ -#define BR_BEARSSL_PEM_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_pem.h - * - * # PEM Support - * - * PEM is a traditional encoding layer use to store binary objects (in - * particular X.509 certificates, and private keys) in text files. While - * the acronym comes from an old, defunct standard ("Privacy Enhanced - * Mail"), the format has been reused, with some variations, by many - * systems, and is a _de facto_ standard, even though it is not, actually, - * specified in all clarity anywhere. - * - * ## Format Details - * - * BearSSL contains a generic, streamed PEM decoder, which handles the - * following format: - * - * - The input source (a sequence of bytes) is assumed to be the - * encoding of a text file in an ASCII-compatible charset. This - * includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each - * line ends on a newline character (U+000A LINE FEED). The - * U+000D CARRIAGE RETURN characters are ignored, so the code - * accepts both Windows-style and Unix-style line endings. - * - * - Each object begins with a banner that occurs at the start of - * a line; the first banner characters are "`-----BEGIN `" (five - * dashes, the word "BEGIN", and a space). The banner matching is - * not case-sensitive. - * - * - The _object name_ consists in the characters that follow the - * banner start sequence, up to the end of the line, but without - * trailing dashes (in "normal" PEM, there are five trailing - * dashes, but this implementation is not picky about these dashes). - * The BearSSL decoder normalises the name characters to uppercase - * (for ASCII letters only) and accepts names up to 127 characters. - * - * - The object ends with a banner that again occurs at the start of - * a line, and starts with "`-----END `" (again case-insensitive). - * - * - Between that start and end banner, only Base64 data shall occur. - * Base64 converts each sequence of three bytes into four - * characters; the four characters are ASCII letters, digits, "`+`" - * or "`-`" signs, and one or two "`=`" signs may occur in the last - * quartet. Whitespace is ignored (whitespace is any ASCII character - * of code 32 or less, so control characters are whitespace) and - * lines may have arbitrary length; the only restriction is that the - * four characters of a quartet must appear on the same line (no - * line break inside a quartet). - * - * - A single file may contain more than one PEM object. Bytes that - * occur between objects are ignored. - * - * - * ## PEM Decoder API - * - * The PEM decoder offers a state-machine API. The caller allocates a - * decoder context, then injects source bytes. Source bytes are pushed - * with `br_pem_decoder_push()`. The decoder stops accepting bytes when - * it reaches an "event", which is either the start of an object, the - * end of an object, or a decoding error within an object. - * - * The `br_pem_decoder_event()` function is used to obtain the current - * event; it also clears it, thus allowing the decoder to accept more - * bytes. When a object start event is raised, the decoder context - * offers the found object name (normalised to ASCII uppercase). - * - * When an object is reached, the caller must set an appropriate callback - * function, which will receive (by chunks) the decoded object data. - * - * Since the decoder context makes no dynamic allocation, it requires - * no explicit deallocation. - */ - -/** - * \brief PEM decoder context. - * - * Contents are opaque (they should not be accessed directly). - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - /* CPU for the T0 virtual machine. */ - struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; - } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; - int err; - - const unsigned char *hbuf; - size_t hlen; - - void (*dest)(void *dest_ctx, const void *src, size_t len); - void *dest_ctx; - - unsigned char event; - char name[128]; - unsigned char buf[255]; - size_t ptr; -#endif -} br_pem_decoder_context; - -/** - * \brief Initialise a PEM decoder structure. - * - * \param ctx decoder context to initialise. - */ -void br_pem_decoder_init(br_pem_decoder_context *ctx); - -/** - * \brief Push some bytes into the decoder. - * - * Returned value is the number of bytes actually consumed; this may be - * less than the number of provided bytes if an event is raised. When an - * event is raised, it must be read (with `br_pem_decoder_event()`); - * until the event is read, this function will return 0. - * - * \param ctx decoder context. - * \param data new data bytes. - * \param len number of new data bytes. - * \return the number of bytes actually received (may be less than `len`). - */ -size_t br_pem_decoder_push(br_pem_decoder_context *ctx, - const void *data, size_t len); - -/** - * \brief Set the receiver for decoded data. - * - * When an object is entered, the provided function (with opaque context - * pointer) will be called repeatedly with successive chunks of decoded - * data for that object. If `dest` is set to 0, then decoded data is - * simply ignored. The receiver can be set at any time, but, in practice, - * it should be called immediately after receiving a "start of object" - * event. - * - * \param ctx decoder context. - * \param dest callback for receiving decoded data. - * \param dest_ctx opaque context pointer for the `dest` callback. - */ -static inline void -br_pem_decoder_setdest(br_pem_decoder_context *ctx, - void (*dest)(void *dest_ctx, const void *src, size_t len), - void *dest_ctx) -{ - ctx->dest = dest; - ctx->dest_ctx = dest_ctx; -} - -/** - * \brief Get the last event. - * - * If an event was raised, then this function returns the event value, and - * also clears it, thereby allowing the decoder to proceed. If no event - * was raised since the last call to `br_pem_decoder_event()`, then this - * function returns 0. - * - * \param ctx decoder context. - * \return the raised event, or 0. - */ -int br_pem_decoder_event(br_pem_decoder_context *ctx); - -/** - * \brief Event: start of object. - * - * This event is raised when the start of a new object has been detected. - * The object name (normalised to uppercase) can be accessed with - * `br_pem_decoder_name()`. - */ -#define BR_PEM_BEGIN_OBJ 1 - -/** - * \brief Event: end of object. - * - * This event is raised when the end of the current object is reached - * (normally, i.e. with no decoding error). - */ -#define BR_PEM_END_OBJ 2 - -/** - * \brief Event: decoding error. - * - * This event is raised when decoding fails within an object. - * This formally closes the current object and brings the decoder back - * to the "out of any object" state. The offending line in the source - * is consumed. - */ -#define BR_PEM_ERROR 3 - -/** - * \brief Get the name of the encountered object. - * - * The encountered object name is defined only when the "start of object" - * event is raised. That name is normalised to uppercase (for ASCII letters - * only) and does not include trailing dashes. - * - * \param ctx decoder context. - * \return the current object name. - */ -static inline const char * -br_pem_decoder_name(br_pem_decoder_context *ctx) -{ - return ctx->name; -} - -/** - * \brief Encode an object in PEM. - * - * This function encodes the provided binary object (`data`, of length `len` - * bytes) into PEM. The `banner` text will be included in the header and - * footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header). - * - * The length (in characters) of the PEM output is returned; that length - * does NOT include the terminating zero, that this function nevertheless - * adds. If using the returned value for allocation purposes, the allocated - * buffer size MUST be at least one byte larger than the returned size. - * - * If `dest` is `NULL`, then the encoding does not happen; however, the - * length of the encoded object is still computed and returned. - * - * The `data` pointer may be `NULL` only if `len` is zero (when encoding - * an object of length zero, which is not very useful), or when `dest` - * is `NULL` (in that case, source data bytes are ignored). - * - * Some `flags` can be specified to alter the encoding behaviour: - * - * - If `BR_PEM_LINE64` is set, then line-breaking will occur after - * every 64 characters of output, instead of the default of 76. - * - * - If `BR_PEM_CRLF` is set, then end-of-line sequence will use - * CR+LF instead of a single LF. - * - * The `data` and `dest` buffers may overlap, in which case the source - * binary data is destroyed in the process. Note that the PEM-encoded output - * is always larger than the source binary. - * - * \param dest the destination buffer (or `NULL`). - * \param data the source buffer (can be `NULL` in some cases). - * \param len the source length (in bytes). - * \param banner the PEM banner expression. - * \param flags the behavioural flags. - * \return the PEM object length (in characters), EXCLUDING the final zero. - */ -size_t br_pem_encode(void *dest, const void *data, size_t len, - const char *banner, unsigned flags); - -/** - * \brief PEM encoding flag: split lines at 64 characters. - */ -#define BR_PEM_LINE64 0x0001 - -/** - * \brief PEM encoding flag: use CR+LF line endings. - */ -#define BR_PEM_CRLF 0x0002 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_prf.h b/src/tls/bearssl/bearssl_prf.h deleted file mode 100644 index fdf608c85..000000000 --- a/src/tls/bearssl/bearssl_prf.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_PRF_H__ -#define BR_BEARSSL_PRF_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_prf.h - * - * # The TLS PRF - * - * The "PRF" is the pseudorandom function used internally during the - * SSL/TLS handshake, notably to expand negotiated shared secrets into - * the symmetric encryption keys that will be used to process the - * application data. - * - * TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This - * is implemented by the `br_tls10_prf()` function. - * - * TLS 1.2 redefines the PRF, using an explicit hash function. The - * `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that - * PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites - * rely on the SHA-256 based PRF, but some use SHA-384. - * - * The PRF always uses as input three parameters: a "secret" (some - * bytes), a "label" (ASCII string), and a "seed" (again some bytes). An - * arbitrary output length can be produced. The "seed" is provided as an - * arbitrary number of binary chunks, that gets internally concatenated. - */ - -/** - * \brief Type for a seed chunk. - * - * Each chunk may have an arbitrary length, and may be empty (no byte at - * all). If the chunk length is zero, then the pointer to the chunk data - * may be `NULL`. - */ -typedef struct { - /** - * \brief Pointer to the chunk data. - */ - const void *data; - - /** - * \brief Chunk length (in bytes). - */ - size_t len; -} br_tls_prf_seed_chunk; - -/** - * \brief PRF implementation for TLS 1.0 and 1.1. - * - * This PRF is the one specified by TLS 1.0 and 1.1. It internally uses - * MD5 and SHA-1. - * - * \param dst destination buffer. - * \param len output length (in bytes). - * \param secret secret value (key) for this computation. - * \param secret_len length of "secret" (in bytes). - * \param label PRF label (zero-terminated ASCII string). - * \param seed_num number of seed chunks. - * \param seed seed chnks for this computation (usually non-secret). - */ -void br_tls10_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed); - -/** - * \brief PRF implementation for TLS 1.2, with SHA-256. - * - * This PRF is the one specified by TLS 1.2, when the underlying hash - * function is SHA-256. - * - * \param dst destination buffer. - * \param len output length (in bytes). - * \param secret secret value (key) for this computation. - * \param secret_len length of "secret" (in bytes). - * \param label PRF label (zero-terminated ASCII string). - * \param seed_num number of seed chunks. - * \param seed seed chnks for this computation (usually non-secret). - */ -void br_tls12_sha256_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed); - -/** - * \brief PRF implementation for TLS 1.2, with SHA-384. - * - * This PRF is the one specified by TLS 1.2, when the underlying hash - * function is SHA-384. - * - * \param dst destination buffer. - * \param len output length (in bytes). - * \param secret secret value (key) for this computation. - * \param secret_len length of "secret" (in bytes). - * \param label PRF label (zero-terminated ASCII string). - * \param seed_num number of seed chunks. - * \param seed seed chnks for this computation (usually non-secret). - */ -void br_tls12_sha384_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed); - -/** - * brief A convenient type name for a PRF implementation. - * - * \param dst destination buffer. - * \param len output length (in bytes). - * \param secret secret value (key) for this computation. - * \param secret_len length of "secret" (in bytes). - * \param label PRF label (zero-terminated ASCII string). - * \param seed_num number of seed chunks. - * \param seed seed chnks for this computation (usually non-secret). - */ -typedef void (*br_tls_prf_impl)(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_rand.h b/src/tls/bearssl/bearssl_rand.h deleted file mode 100644 index 0a9f544fc..000000000 --- a/src/tls/bearssl/bearssl_rand.h +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_RAND_H__ -#define BR_BEARSSL_RAND_H__ - -#include -#include - -#include "bearssl_block.h" -#include "bearssl_hash.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_rand.h - * - * # Pseudo-Random Generators - * - * A PRNG is a state-based engine that outputs pseudo-random bytes on - * demand. It is initialized with an initial seed, and additional seed - * bytes can be added afterwards. Bytes produced depend on the seeds and - * also on the exact sequence of calls (including sizes requested for - * each call). - * - * - * ## Procedural and OOP API - * - * For the PRNG of name "`xxx`", two API are provided. The _procedural_ - * API defined a context structure `br_xxx_context` and three functions: - * - * - `br_xxx_init()` - * - * Initialise the context with an initial seed. - * - * - `br_xxx_generate()` - * - * Produce some pseudo-random bytes. - * - * - `br_xxx_update()` - * - * Inject some additional seed. - * - * The initialisation function sets the first context field (`vtable`) - * to a pointer to the vtable that supports the OOP API. The OOP API - * provides access to the same functions through function pointers, - * named `init()`, `generate()` and `update()`. - * - * Note that the context initialisation method may accept additional - * parameters, provided as a 'const void *' pointer at API level. These - * additional parameters depend on the implemented PRNG. - * - * - * ## HMAC_DRBG - * - * HMAC_DRBG is defined in [NIST SP 800-90A Revision - * 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf). - * It uses HMAC repeatedly, over some configurable underlying hash - * function. In BearSSL, it is implemented under the "`hmac_drbg`" name. - * The "extra parameters" pointer for context initialisation should be - * set to a pointer to the vtable for the underlying hash function (e.g. - * pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256). - * - * According to the NIST standard, each request shall produce up to - * 219 bits (i.e. 64 kB of data); moreover, the context shall - * be reseeded at least once every 248 requests. This - * implementation does not maintain the reseed counter (the threshold is - * too high to be reached in practice) and does not object to producing - * more than 64 kB in a single request; thus, the code cannot fail, - * which corresponds to the fact that the API has no room for error - * codes. However, this implies that requesting more than 64 kB in one - * `generate()` request, or making more than 248 requests - * without reseeding, is formally out of NIST specification. There is - * no currently known security penalty for exceeding the NIST limits, - * and, in any case, HMAC_DRBG usage in implementing SSL/TLS always - * stays much below these thresholds. - * - * - * ## AESCTR_DRBG - * - * AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is - * meant to be used only in situations where you are desperate for - * speed, and have an hardware-optimized AES/CTR implementation. Whether - * this will yield perceptible improvements depends on what you use the - * pseudorandom bytes for, and how many you want; for instance, RSA key - * pair generation uses a substantial amount of randomness, and using - * AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key - * generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz). - * - * Internally, it uses CTR mode with successive counter values, starting - * at zero (counter value expressed over 128 bits, big-endian convention). - * The counter is not allowed to reach 32768; thus, every 32768*16 bytes - * at most, the `update()` function is run (on an empty seed, if none is - * provided). The `update()` function computes the new AES-128 key by - * applying a custom hash function to the concatenation of a state-dependent - * word (encryption of an all-one block with the current key) and the new - * seed. The custom hash function uses Hirose's construction over AES-256; - * see the comments in `aesctr_drbg.c` for details. - * - * This DRBG does not follow an existing standard, and thus should be - * considered as inadequate for production use until it has been properly - * analysed. - */ - -/** - * \brief Class type for PRNG implementations. - * - * A `br_prng_class` instance references the methods implementing a PRNG. - * Constant instances of this structure are defined for each implemented - * PRNG. Such instances are also called "vtables". - */ -typedef struct br_prng_class_ br_prng_class; -struct br_prng_class_ { - /** - * \brief Size (in bytes) of the context structure appropriate for - * running this PRNG. - */ - size_t context_size; - - /** - * \brief Initialisation method. - * - * The context to initialise is provided as a pointer to its - * first field (the vtable pointer); this function sets that - * first field to a pointer to the vtable. - * - * The extra parameters depend on the implementation; each - * implementation defines what kind of extra parameters it - * expects (if any). - * - * Requirements on the initial seed depend on the implemented - * PRNG. - * - * \param ctx PRNG context to initialise. - * \param params extra parameters for the PRNG. - * \param seed initial seed. - * \param seed_len initial seed length (in bytes). - */ - void (*init)(const br_prng_class **ctx, const void *params, - const void *seed, size_t seed_len); - - /** - * \brief Random bytes generation. - * - * This method produces `len` pseudorandom bytes, in the `out` - * buffer. The context is updated accordingly. - * - * \param ctx PRNG context. - * \param out output buffer. - * \param len number of pseudorandom bytes to produce. - */ - void (*generate)(const br_prng_class **ctx, void *out, size_t len); - - /** - * \brief Inject additional seed bytes. - * - * The provided seed bytes are added into the PRNG internal - * entropy pool. - * - * \param ctx PRNG context. - * \param seed additional seed. - * \param seed_len additional seed length (in bytes). - */ - void (*update)(const br_prng_class **ctx, - const void *seed, size_t seed_len); -}; - -/** - * \brief Context for HMAC_DRBG. - * - * The context contents are opaque, except the first field, which - * supports OOP. - */ -typedef struct { - /** - * \brief Pointer to the vtable. - * - * This field is set with the initialisation method/function. - */ - const br_prng_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char K[64]; - unsigned char V[64]; - const br_hash_class *digest_class; -#endif -} br_hmac_drbg_context; - -/** - * \brief Statically allocated, constant vtable for HMAC_DRBG. - */ -extern const br_prng_class br_hmac_drbg_vtable; - -/** - * \brief HMAC_DRBG initialisation. - * - * The context to initialise is provided as a pointer to its first field - * (the vtable pointer); this function sets that first field to a - * pointer to the vtable. - * - * The `seed` value is what is called, in NIST terminology, the - * concatenation of the "seed", "nonce" and "personalization string", in - * that order. - * - * The `digest_class` parameter defines the underlying hash function. - * Formally, the NIST standard specifies that the hash function shall - * be only SHA-1 or one of the SHA-2 functions. This implementation also - * works with any other implemented hash function (such as MD5), but - * this is non-standard and therefore not recommended. - * - * \param ctx HMAC_DRBG context to initialise. - * \param digest_class vtable for the underlying hash function. - * \param seed initial seed. - * \param seed_len initial seed length (in bytes). - */ -void br_hmac_drbg_init(br_hmac_drbg_context *ctx, - const br_hash_class *digest_class, const void *seed, size_t seed_len); - -/** - * \brief Random bytes generation with HMAC_DRBG. - * - * This method produces `len` pseudorandom bytes, in the `out` - * buffer. The context is updated accordingly. Formally, requesting - * more than 65536 bytes in one request falls out of specification - * limits (but it won't fail). - * - * \param ctx HMAC_DRBG context. - * \param out output buffer. - * \param len number of pseudorandom bytes to produce. - */ -void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); - -/** - * \brief Inject additional seed bytes in HMAC_DRBG. - * - * The provided seed bytes are added into the HMAC_DRBG internal - * entropy pool. The process does not _replace_ existing entropy, - * thus pushing non-random bytes (i.e. bytes which are known to the - * attackers) does not degrade the overall quality of generated bytes. - * - * \param ctx HMAC_DRBG context. - * \param seed additional seed. - * \param seed_len additional seed length (in bytes). - */ -void br_hmac_drbg_update(br_hmac_drbg_context *ctx, - const void *seed, size_t seed_len); - -/** - * \brief Get the hash function implementation used by a given instance of - * HMAC_DRBG. - * - * This calls MUST NOT be performed on a context which was not - * previously initialised. - * - * \param ctx HMAC_DRBG context. - * \return the hash function vtable. - */ -static inline const br_hash_class * -br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx) -{ - return ctx->digest_class; -} - -/** - * \brief Type for a provider of entropy seeds. - * - * A "seeder" is a function that is able to obtain random values from - * some source and inject them as entropy seed in a PRNG. A seeder - * shall guarantee that the total entropy of the injected seed is large - * enough to seed a PRNG for purposes of cryptographic key generation - * (i.e. at least 128 bits). - * - * A seeder may report a failure to obtain adequate entropy. Seeders - * shall endeavour to fix themselves transient errors by trying again; - * thus, callers may consider reported errors as permanent. - * - * \param ctx PRNG context to seed. - * \return 1 on success, 0 on error. - */ -typedef int (*br_prng_seeder)(const br_prng_class **ctx); - -/** - * \brief Get a seeder backed by the operating system or hardware. - * - * Get a seeder that feeds on RNG facilities provided by the current - * operating system or hardware. If no such facility is known, then 0 - * is returned. - * - * If `name` is not `NULL`, then `*name` is set to a symbolic string - * that identifies the seeder implementation. If no seeder is returned - * and `name` is not `NULL`, then `*name` is set to a pointer to the - * constant string `"none"`. - * - * \param name receiver for seeder name, or `NULL`. - * \return the system seeder, if available, or 0. - */ -br_prng_seeder br_prng_seeder_system(const char **name); - -/** - * \brief Context for AESCTR_DRBG. - * - * The context contents are opaque, except the first field, which - * supports OOP. - */ -typedef struct { - /** - * \brief Pointer to the vtable. - * - * This field is set with the initialisation method/function. - */ - const br_prng_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - br_aes_gen_ctr_keys sk; - uint32_t cc; -#endif -} br_aesctr_drbg_context; - -/** - * \brief Statically allocated, constant vtable for AESCTR_DRBG. - */ -extern const br_prng_class br_aesctr_drbg_vtable; - -/** - * \brief AESCTR_DRBG initialisation. - * - * The context to initialise is provided as a pointer to its first field - * (the vtable pointer); this function sets that first field to a - * pointer to the vtable. - * - * The internal AES key is first set to the all-zero key; then, the - * `br_aesctr_drbg_update()` function is called with the provided `seed`. - * The call is performed even if the seed length (`seed_len`) is zero. - * - * The `aesctr` parameter defines the underlying AES/CTR implementation. - * - * \param ctx AESCTR_DRBG context to initialise. - * \param aesctr vtable for the AES/CTR implementation. - * \param seed initial seed (can be `NULL` if `seed_len` is zero). - * \param seed_len initial seed length (in bytes). - */ -void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx, - const br_block_ctr_class *aesctr, const void *seed, size_t seed_len); - -/** - * \brief Random bytes generation with AESCTR_DRBG. - * - * This method produces `len` pseudorandom bytes, in the `out` - * buffer. The context is updated accordingly. - * - * \param ctx AESCTR_DRBG context. - * \param out output buffer. - * \param len number of pseudorandom bytes to produce. - */ -void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, - void *out, size_t len); - -/** - * \brief Inject additional seed bytes in AESCTR_DRBG. - * - * The provided seed bytes are added into the AESCTR_DRBG internal - * entropy pool. The process does not _replace_ existing entropy, - * thus pushing non-random bytes (i.e. bytes which are known to the - * attackers) does not degrade the overall quality of generated bytes. - * - * \param ctx AESCTR_DRBG context. - * \param seed additional seed. - * \param seed_len additional seed length (in bytes). - */ -void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, - const void *seed, size_t seed_len); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_rsa.h b/src/tls/bearssl/bearssl_rsa.h deleted file mode 100644 index 805fb34cc..000000000 --- a/src/tls/bearssl/bearssl_rsa.h +++ /dev/null @@ -1,1366 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_RSA_H__ -#define BR_BEARSSL_RSA_H__ - -#include -#include - -#include "bearssl_rand.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_rsa.h - * - * # RSA - * - * This file documents the RSA implementations provided with BearSSL. - * Note that the SSL engine accesses these implementations through a - * configurable API, so it is possible to, for instance, run a SSL - * server which uses a RSA engine which is not based on this code. - * - * ## Key Elements - * - * RSA public and private keys consist in lists of big integers. All - * such integers are represented with big-endian unsigned notation: - * first byte is the most significant, and the value is positive (so - * there is no dedicated "sign bit"). Public and private key structures - * thus contain, for each such integer, a pointer to the first value byte - * (`unsigned char *`), and a length (`size_t`) which is the number of - * relevant bytes. As a general rule, minimal-length encoding is not - * enforced: values may have extra leading bytes of value 0. - * - * RSA public keys consist in two integers: - * - * - the modulus (`n`); - * - the public exponent (`e`). - * - * RSA private keys, as defined in - * [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers: - * - * - the modulus (`n`); - * - the public exponent (`e`); - * - the private exponent (`d`); - * - the first prime factor (`p`); - * - the second prime factor (`q`); - * - the first reduced exponent (`dp`, which is `d` modulo `p-1`); - * - the second reduced exponent (`dq`, which is `d` modulo `q-1`); - * - the CRT coefficient (`iq`, the inverse of `q` modulo `p`). - * - * However, the implementations defined in BearSSL use only five of - * these integers: `p`, `q`, `dp`, `dq` and `iq`. - * - * ## Security Features and Limitations - * - * The implementations contained in BearSSL have the following limitations - * and features: - * - * - They are constant-time. This means that the execution time and - * memory access pattern may depend on the _lengths_ of the private - * key components, but not on their value, nor on the value of - * the operand. Note that this property is not achieved through - * random masking, but "true" constant-time code. - * - * - They support only private keys with two prime factors. RSA private - * keys with three or more prime factors are nominally supported, but - * rarely used; they may offer faster operations, at the expense of - * more code and potentially a reduction in security if there are - * "too many" prime factors. - * - * - The public exponent may have arbitrary length. Of course, it is - * a good idea to keep public exponents small, so that public key - * operations are fast; but, contrary to some widely deployed - * implementations, BearSSL has no problem with public exponents - * longer than 32 bits. - * - * - The two prime factors of the modulus need not have the same length - * (but severely imbalanced factor lengths might reduce security). - * Similarly, there is no requirement that the first factor (`p`) - * be greater than the second factor (`q`). - * - * - Prime factors and modulus must be smaller than a compile-time limit. - * This is made necessary by the use of fixed-size stack buffers, and - * the limit has been adjusted to keep stack usage under 2 kB for the - * RSA operations. Currently, the maximum modulus size is 4096 bits, - * and the maximum prime factor size is 2080 bits. - * - * - The RSA functions themselves do not enforce lower size limits, - * except that which is absolutely necessary for the operation to - * mathematically make sense (e.g. a PKCS#1 v1.5 signature with - * SHA-1 requires a modulus of at least 361 bits). It is up to users - * of this code to enforce size limitations when appropriate (e.g. - * the X.509 validation engine, by default, rejects RSA keys of - * less than 1017 bits). - * - * - Within the size constraints expressed above, arbitrary bit lengths - * are supported. There is no requirement that prime factors or - * modulus have a size multiple of 8 or 16. - * - * - When verifying PKCS#1 v1.5 signatures, both variants of the hash - * function identifying header (with and without the ASN.1 NULL) are - * supported. When producing such signatures, the variant with the - * ASN.1 NULL is used. - * - * ## Implementations - * - * Three RSA implementations are included: - * - * - The **i32** implementation internally represents big integers - * as arrays of 32-bit integers. It is perfunctory and portable, - * but not very efficient. - * - * - The **i31** implementation uses 32-bit integers, each containing - * 31 bits worth of integer data. The i31 implementation is somewhat - * faster than the i32 implementation (the reduced integer size makes - * carry propagation easier) for a similar code footprint, but uses - * very slightly larger stack buffers (about 4% bigger). - * - * - The **i62** implementation is similar to the i31 implementation, - * except that it internally leverages the 64x64->128 multiplication - * opcode. This implementation is available only on architectures - * where such an opcode exists. It is much faster than i31. - * - * - The **i15** implementation uses 16-bit integers, each containing - * 15 bits worth of integer data. Multiplication results fit on - * 32 bits, so this won't use the "widening" multiplication routine - * on ARM Cortex M0/M0+, for much better performance and constant-time - * execution. - */ - -/** - * \brief RSA public key. - * - * The structure references the modulus and the public exponent. Both - * integers use unsigned big-endian representation; extra leading bytes - * of value 0 are allowed. - */ -typedef struct { - /** \brief Modulus. */ - unsigned char *n; - /** \brief Modulus length (in bytes). */ - size_t nlen; - /** \brief Public exponent. */ - unsigned char *e; - /** \brief Public exponent length (in bytes). */ - size_t elen; -} br_rsa_public_key; - -/** - * \brief RSA private key. - * - * The structure references the private factors, reduced private - * exponents, and CRT coefficient. It also contains the bit length of - * the modulus. The big integers use unsigned big-endian representation; - * extra leading bytes of value 0 are allowed. However, the modulus bit - * length (`n_bitlen`) MUST be exact. - */ -typedef struct { - /** \brief Modulus bit length (in bits, exact value). */ - uint32_t n_bitlen; - /** \brief First prime factor. */ - unsigned char *p; - /** \brief First prime factor length (in bytes). */ - size_t plen; - /** \brief Second prime factor. */ - unsigned char *q; - /** \brief Second prime factor length (in bytes). */ - size_t qlen; - /** \brief First reduced private exponent. */ - unsigned char *dp; - /** \brief First reduced private exponent length (in bytes). */ - size_t dplen; - /** \brief Second reduced private exponent. */ - unsigned char *dq; - /** \brief Second reduced private exponent length (in bytes). */ - size_t dqlen; - /** \brief CRT coefficient. */ - unsigned char *iq; - /** \brief CRT coefficient length (in bytes). */ - size_t iqlen; -} br_rsa_private_key; - -/** - * \brief Type for a RSA public key engine. - * - * The public key engine performs the modular exponentiation of the - * provided value with the public exponent. The value is modified in - * place. - * - * The value length (`xlen`) is verified to have _exactly_ the same - * length as the modulus (actual modulus length, without extra leading - * zeros in the modulus representation in memory). If the length does - * not match, then this function returns 0 and `x[]` is unmodified. - * - * It `xlen` is correct, then `x[]` is modified. Returned value is 1 - * on success, 0 on error. Error conditions include an oversized `x[]` - * (the array has the same length as the modulus, but the numerical value - * is not lower than the modulus) and an invalid modulus (e.g. an even - * integer). If an error is reported, then the new contents of `x[]` are - * unspecified. - * - * \param x operand to exponentiate. - * \param xlen length of the operand (in bytes). - * \param pk RSA public key. - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk); - -/** - * \brief Type for a RSA signature verification engine (PKCS#1 v1.5). - * - * Parameters are: - * - * - The signature itself. The provided array is NOT modified. - * - * - The encoded OID for the hash function. The provided array must begin - * with a single byte that contains the length of the OID value (in - * bytes), followed by exactly that many bytes. This parameter may - * also be `NULL`, in which case the raw hash value should be used - * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up - * to TLS-1.1, with a 36-byte hash value). - * - * - The hash output length, in bytes. - * - * - The public key. - * - * - An output buffer for the hash value. The caller must still compare - * it with the hash of the data over which the signature is computed. - * - * **Constraints:** - * - * - Hash length MUST be no more than 64 bytes. - * - * - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]` - * must have a value in the 0..32 range, inclusive). - * - * This function verifies that the signature length (`xlen`) matches the - * modulus length (this function returns 0 on mismatch). If the modulus - * size exceeds the maximum supported RSA size, then the function also - * returns 0. - * - * Returned value is 1 on success, 0 on error. - * - * Implementations of this type need not be constant-time. - * - * \param x signature buffer. - * \param xlen signature length (in bytes). - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash_len expected hash value length (in bytes). - * \param pk RSA public key. - * \param hash_out output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out); - -/** - * \brief Type for a RSA encryption engine (OAEP). - * - * Parameters are: - * - * - A source of random bytes. The source must be already initialized. - * - * - A hash function, used internally with the mask generation function - * (MGF1). - * - * - A label. The `label` pointer may be `NULL` if `label_len` is zero - * (an empty label, which is the default in PKCS#1 v2.2). - * - * - The public key. - * - * - The destination buffer. Its maximum length (in bytes) is provided; - * if that length is lower than the public key length, then an error - * is reported. - * - * - The source message. - * - * The encrypted message output has exactly the same length as the modulus - * (mathematical length, in bytes, not counting extra leading zeros in the - * modulus representation in the public key). - * - * The source message (`src`, length `src_len`) may overlap with the - * destination buffer (`dst`, length `dst_max_len`). - * - * This function returns the actual encrypted message length, in bytes; - * on error, zero is returned. An error is reported if the output buffer - * is not large enough, or the public is invalid, or the public key - * modulus exceeds the maximum supported RSA size. - * - * \param rnd source of random bytes. - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param pk RSA public key. - * \param dst destination buffer. - * \param dst_max_len destination buffer length (maximum encrypted data size). - * \param src message to encrypt. - * \param src_len source message length (in bytes). - * \return encrypted message length (in bytes), or 0 on error. - */ -typedef size_t (*br_rsa_oaep_encrypt)( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len); - -/** - * \brief Type for a RSA private key engine. - * - * The `x[]` buffer is modified in place, and its length is inferred from - * the modulus length (`x[]` is assumed to have a length of - * `(sk->n_bitlen+7)/8` bytes). - * - * Returned value is 1 on success, 0 on error. - * - * \param x operand to exponentiate. - * \param sk RSA private key. - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_rsa_private)(unsigned char *x, - const br_rsa_private_key *sk); - -/** - * \brief Type for a RSA signature generation engine (PKCS#1 v1.5). - * - * Parameters are: - * - * - The encoded OID for the hash function. The provided array must begin - * with a single byte that contains the length of the OID value (in - * bytes), followed by exactly that many bytes. This parameter may - * also be `NULL`, in which case the raw hash value should be used - * with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up - * to TLS-1.1, with a 36-byte hash value). - * - * - The hash value computes over the data to sign (its length is - * expressed in bytes). - * - * - The RSA private key. - * - * - The output buffer, that receives the signature. - * - * Returned value is 1 on success, 0 on error. Error conditions include - * a too small modulus for the provided hash OID and value, or some - * invalid key parameters. The signature length is exactly - * `(sk->n_bitlen+7)/8` bytes. - * - * This function is expected to be constant-time with regards to the - * private key bytes (lengths of the modulus and the individual factors - * may leak, though) and to the hashed data. - * - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash hash value. - * \param hash_len hash value length (in bytes). - * \param sk RSA private key. - * \param x output buffer for the signature value. - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x); - -/** - * \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures). - */ -#define BR_HASH_OID_SHA1 \ - ((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A") - -/** - * \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures). - */ -#define BR_HASH_OID_SHA224 \ - ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04") - -/** - * \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures). - */ -#define BR_HASH_OID_SHA256 \ - ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01") - -/** - * \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures). - */ -#define BR_HASH_OID_SHA384 \ - ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02") - -/** - * \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures). - */ -#define BR_HASH_OID_SHA512 \ - ((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03") - -/** - * \brief Type for a RSA decryption engine (OAEP). - * - * Parameters are: - * - * - A hash function, used internally with the mask generation function - * (MGF1). - * - * - A label. The `label` pointer may be `NULL` if `label_len` is zero - * (an empty label, which is the default in PKCS#1 v2.2). - * - * - The private key. - * - * - The source and destination buffer. The buffer initially contains - * the encrypted message; the buffer contents are altered, and the - * decrypted message is written at the start of that buffer - * (decrypted message is always shorter than the encrypted message). - * - * If decryption fails in any way, then `*len` is unmodified, and the - * function returns 0. Otherwise, `*len` is set to the decrypted message - * length, and 1 is returned. The implementation is responsible for - * checking that the input message length matches the key modulus length, - * and that the padding is correct. - * - * Implementations MUST use constant-time check of the validity of the - * OAEP padding, at least until the leading byte and hash value have - * been checked. Whether overall decryption worked, and the length of - * the decrypted message, may leak. - * - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len encrypted/decrypted message length. - * \return 1 on success, 0 on error. - */ -typedef uint32_t (*br_rsa_oaep_decrypt)( - const br_hash_class *dig, const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len); - -/* - * RSA "i32" engine. Integers are internally represented as arrays of - * 32-bit integers, and the core multiplication primitive is the - * 32x32->64 multiplication. - */ - -/** - * \brief RSA public key engine "i32". - * - * \see br_rsa_public - * - * \param x operand to exponentiate. - * \param xlen length of the operand (in bytes). - * \param pk RSA public key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk); - -/** - * \brief RSA signature verification engine "i32". - * - * \see br_rsa_pkcs1_vrfy - * - * \param x signature buffer. - * \param xlen signature length (in bytes). - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash_len expected hash value length (in bytes). - * \param pk RSA public key. - * \param hash_out output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out); - -/** - * \brief RSA private key engine "i32". - * - * \see br_rsa_private - * - * \param x operand to exponentiate. - * \param sk RSA private key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i32_private(unsigned char *x, - const br_rsa_private_key *sk); - -/** - * \brief RSA signature generation engine "i32". - * - * \see br_rsa_pkcs1_sign - * - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash hash value. - * \param hash_len hash value length (in bytes). - * \param sk RSA private key. - * \param x output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x); - -/* - * RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit - * word. This uses slightly more stack space (about 4% more) and code - * space, but it quite faster. - */ - -/** - * \brief RSA public key engine "i31". - * - * \see br_rsa_public - * - * \param x operand to exponentiate. - * \param xlen length of the operand (in bytes). - * \param pk RSA public key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk); - -/** - * \brief RSA signature verification engine "i31". - * - * \see br_rsa_pkcs1_vrfy - * - * \param x signature buffer. - * \param xlen signature length (in bytes). - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash_len expected hash value length (in bytes). - * \param pk RSA public key. - * \param hash_out output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out); - -/** - * \brief RSA private key engine "i31". - * - * \see br_rsa_private - * - * \param x operand to exponentiate. - * \param sk RSA private key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i31_private(unsigned char *x, - const br_rsa_private_key *sk); - -/** - * \brief RSA signature generation engine "i31". - * - * \see br_rsa_pkcs1_sign - * - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash hash value. - * \param hash_len hash value length (in bytes). - * \param sk RSA private key. - * \param x output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x); - -/* - * RSA "i62" engine. Similar to i31, but internal multiplication use - * 64x64->128 multiplications. This is available only on architecture - * that offer such an opcode. - */ - -/** - * \brief RSA public key engine "i62". - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_public - * - * \param x operand to exponentiate. - * \param xlen length of the operand (in bytes). - * \param pk RSA public key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk); - -/** - * \brief RSA signature verification engine "i62". - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_pkcs1_vrfy - * - * \param x signature buffer. - * \param xlen signature length (in bytes). - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash_len expected hash value length (in bytes). - * \param pk RSA public key. - * \param hash_out output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out); - -/** - * \brief RSA private key engine "i62". - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_private - * - * \param x operand to exponentiate. - * \param sk RSA private key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i62_private(unsigned char *x, - const br_rsa_private_key *sk); - -/** - * \brief RSA signature generation engine "i62". - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_pkcs1_sign - * - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash hash value. - * \param hash_len hash value length (in bytes). - * \param sk RSA private key. - * \param x output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x); - -/** - * \brief Get the RSA "i62" implementation (public key operations), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_public br_rsa_i62_public_get(void); - -/** - * \brief Get the RSA "i62" implementation (PKCS#1 signature verification), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void); - -/** - * \brief Get the RSA "i62" implementation (private key operations), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_private br_rsa_i62_private_get(void); - -/** - * \brief Get the RSA "i62" implementation (PKCS#1 signature generation), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void); - -/** - * \brief Get the RSA "i62" implementation (OAEP encryption), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void); - -/** - * \brief Get the RSA "i62" implementation (OAEP decryption), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void); - -/* - * RSA "i15" engine. Integers are represented as 15-bit integers, so - * the code uses only 32-bit multiplication (no 64-bit result), which - * is vastly faster (and constant-time) on the ARM Cortex M0/M0+. - */ - -/** - * \brief RSA public key engine "i15". - * - * \see br_rsa_public - * - * \param x operand to exponentiate. - * \param xlen length of the operand (in bytes). - * \param pk RSA public key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk); - -/** - * \brief RSA signature verification engine "i15". - * - * \see br_rsa_pkcs1_vrfy - * - * \param x signature buffer. - * \param xlen signature length (in bytes). - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash_len expected hash value length (in bytes). - * \param pk RSA public key. - * \param hash_out output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out); - -/** - * \brief RSA private key engine "i15". - * - * \see br_rsa_private - * - * \param x operand to exponentiate. - * \param sk RSA private key. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i15_private(unsigned char *x, - const br_rsa_private_key *sk); - -/** - * \brief RSA signature generation engine "i15". - * - * \see br_rsa_pkcs1_sign - * - * \param hash_oid encoded hash algorithm OID (or `NULL`). - * \param hash hash value. - * \param hash_len hash value length (in bytes). - * \param sk RSA private key. - * \param x output buffer for the hash value. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x); - -/** - * \brief Get "default" RSA implementation (public-key operations). - * - * This returns the preferred implementation of RSA (public-key operations) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_public br_rsa_public_get_default(void); - -/** - * \brief Get "default" RSA implementation (private-key operations). - * - * This returns the preferred implementation of RSA (private-key operations) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_private br_rsa_private_get_default(void); - -/** - * \brief Get "default" RSA implementation (PKCS#1 signature verification). - * - * This returns the preferred implementation of RSA (signature verification) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void); - -/** - * \brief Get "default" RSA implementation (PKCS#1 signature generation). - * - * This returns the preferred implementation of RSA (signature generation) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void); - -/** - * \brief Get "default" RSA implementation (OAEP encryption). - * - * This returns the preferred implementation of RSA (OAEP encryption) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void); - -/** - * \brief Get "default" RSA implementation (OAEP decryption). - * - * This returns the preferred implementation of RSA (OAEP decryption) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void); - -/** - * \brief RSA decryption helper, for SSL/TLS. - * - * This function performs the RSA decryption for a RSA-based key exchange - * in a SSL/TLS server. The provided RSA engine is used. The `data` - * parameter points to the value to decrypt, of length `len` bytes. On - * success, the 48-byte pre-master secret is copied into `data`, starting - * at the first byte of that buffer; on error, the contents of `data` - * become indeterminate. - * - * This function first checks that the provided value length (`len`) is - * not lower than 59 bytes, and matches the RSA modulus length; if neither - * of this property is met, then this function returns 0 and the buffer - * is unmodified. - * - * Otherwise, decryption and then padding verification are performed, both - * in constant-time. A decryption error, or a bad padding, or an - * incorrect decrypted value length are reported with a returned value of - * 0; on success, 1 is returned. The caller (SSL server engine) is supposed - * to proceed with a random pre-master secret in case of error. - * - * \param core RSA private key engine. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len length (in bytes) of the data to decrypt. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, - unsigned char *data, size_t len); - -/** - * \brief RSA encryption (OAEP) with the "i15" engine. - * - * \see br_rsa_oaep_encrypt - * - * \param rnd source of random bytes. - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param pk RSA public key. - * \param dst destination buffer. - * \param dst_max_len destination buffer length (maximum encrypted data size). - * \param src message to encrypt. - * \param src_len source message length (in bytes). - * \return encrypted message length (in bytes), or 0 on error. - */ -size_t br_rsa_i15_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len); - -/** - * \brief RSA decryption (OAEP) with the "i15" engine. - * - * \see br_rsa_oaep_decrypt - * - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len encrypted/decrypted message length. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i15_oaep_decrypt( - const br_hash_class *dig, const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len); - -/** - * \brief RSA encryption (OAEP) with the "i31" engine. - * - * \see br_rsa_oaep_encrypt - * - * \param rnd source of random bytes. - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param pk RSA public key. - * \param dst destination buffer. - * \param dst_max_len destination buffer length (maximum encrypted data size). - * \param src message to encrypt. - * \param src_len source message length (in bytes). - * \return encrypted message length (in bytes), or 0 on error. - */ -size_t br_rsa_i31_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len); - -/** - * \brief RSA decryption (OAEP) with the "i31" engine. - * - * \see br_rsa_oaep_decrypt - * - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len encrypted/decrypted message length. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i31_oaep_decrypt( - const br_hash_class *dig, const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len); - -/** - * \brief RSA encryption (OAEP) with the "i32" engine. - * - * \see br_rsa_oaep_encrypt - * - * \param rnd source of random bytes. - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param pk RSA public key. - * \param dst destination buffer. - * \param dst_max_len destination buffer length (maximum encrypted data size). - * \param src message to encrypt. - * \param src_len source message length (in bytes). - * \return encrypted message length (in bytes), or 0 on error. - */ -size_t br_rsa_i32_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len); - -/** - * \brief RSA decryption (OAEP) with the "i32" engine. - * - * \see br_rsa_oaep_decrypt - * - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len encrypted/decrypted message length. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i32_oaep_decrypt( - const br_hash_class *dig, const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len); - -/** - * \brief RSA encryption (OAEP) with the "i62" engine. - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_oaep_encrypt - * - * \param rnd source of random bytes. - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param pk RSA public key. - * \param dst destination buffer. - * \param dst_max_len destination buffer length (maximum encrypted data size). - * \param src message to encrypt. - * \param src_len source message length (in bytes). - * \return encrypted message length (in bytes), or 0 on error. - */ -size_t br_rsa_i62_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len); - -/** - * \brief RSA decryption (OAEP) with the "i62" engine. - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_oaep_decrypt - * - * \param dig hash function to use with MGF1. - * \param label label value (may be `NULL` if `label_len` is zero). - * \param label_len label length, in bytes. - * \param sk RSA private key. - * \param data input/output buffer. - * \param len encrypted/decrypted message length. - * \return 1 on success, 0 on error. - */ -uint32_t br_rsa_i62_oaep_decrypt( - const br_hash_class *dig, const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len); - -/** - * \brief Get buffer size to hold RSA private key elements. - * - * This macro returns the length (in bytes) of the buffer needed to - * receive the elements of a RSA private key, as generated by one of - * the `br_rsa_*_keygen()` functions. If the provided size is a constant - * expression, then the whole macro evaluates to a constant expression. - * - * \param size target key size (modulus size, in bits) - * \return the length of the private key buffer, in bytes. - */ -#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4)) - -/** - * \brief Get buffer size to hold RSA public key elements. - * - * This macro returns the length (in bytes) of the buffer needed to - * receive the elements of a RSA public key, as generated by one of - * the `br_rsa_*_keygen()` functions. If the provided size is a constant - * expression, then the whole macro evaluates to a constant expression. - * - * \param size target key size (modulus size, in bits) - * \return the length of the public key buffer, in bytes. - */ -#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3)) - -/** - * \brief Type for RSA key pair generator implementation. - * - * This function generates a new RSA key pair whose modulus has bit - * length `size` bits. The private key elements are written in the - * `kbuf_priv` buffer, and pointer values and length fields to these - * elements are populated in the provided private key structure `sk`. - * Similarly, the public key elements are written in `kbuf_pub`, with - * pointers and lengths set in `pk`. - * - * If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the - * private key is set. - * - * If `pubexp` is not zero, then its value will be used as public - * exponent. Valid RSA public exponent values are odd integers - * greater than 1. If `pubexp` is zero, then the public exponent will - * have value 3. - * - * The provided PRNG (`rng_ctx`) must have already been initialized - * and seeded. - * - * Returned value is 1 on success, 0 on error. An error is reported - * if the requested range is outside of the supported key sizes, or - * if an invalid non-zero public exponent value is provided. Supported - * range starts at 512 bits, and up to an implementation-defined - * maximum (by default 4096 bits). Note that key sizes up to 768 bits - * have been broken in practice, and sizes lower than 2048 bits are - * usually considered to be weak and should not be used. - * - * \param rng_ctx source PRNG context (already initialized) - * \param sk RSA private key structure (destination) - * \param kbuf_priv buffer for private key elements - * \param pk RSA public key structure (destination), or `NULL` - * \param kbuf_pub buffer for public key elements, or `NULL` - * \param size target RSA modulus size (in bits) - * \param pubexp public exponent to use, or zero - * \return 1 on success, 0 on error (invalid parameters) - */ -typedef uint32_t (*br_rsa_keygen)( - const br_prng_class **rng_ctx, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp); - -/** - * \brief RSA key pair generation with the "i15" engine. - * - * \see br_rsa_keygen - * - * \param rng_ctx source PRNG context (already initialized) - * \param sk RSA private key structure (destination) - * \param kbuf_priv buffer for private key elements - * \param pk RSA public key structure (destination), or `NULL` - * \param kbuf_pub buffer for public key elements, or `NULL` - * \param size target RSA modulus size (in bits) - * \param pubexp public exponent to use, or zero - * \return 1 on success, 0 on error (invalid parameters) - */ -uint32_t br_rsa_i15_keygen( - const br_prng_class **rng_ctx, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp); - -/** - * \brief RSA key pair generation with the "i31" engine. - * - * \see br_rsa_keygen - * - * \param rng_ctx source PRNG context (already initialized) - * \param sk RSA private key structure (destination) - * \param kbuf_priv buffer for private key elements - * \param pk RSA public key structure (destination), or `NULL` - * \param kbuf_pub buffer for public key elements, or `NULL` - * \param size target RSA modulus size (in bits) - * \param pubexp public exponent to use, or zero - * \return 1 on success, 0 on error (invalid parameters) - */ -uint32_t br_rsa_i31_keygen( - const br_prng_class **rng_ctx, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp); - -/** - * \brief RSA key pair generation with the "i62" engine. - * - * This function is defined only on architecture that offer a 64x64->128 - * opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer - * to that function. - * - * \see br_rsa_keygen - * - * \param rng_ctx source PRNG context (already initialized) - * \param sk RSA private key structure (destination) - * \param kbuf_priv buffer for private key elements - * \param pk RSA public key structure (destination), or `NULL` - * \param kbuf_pub buffer for public key elements, or `NULL` - * \param size target RSA modulus size (in bits) - * \param pubexp public exponent to use, or zero - * \return 1 on success, 0 on error (invalid parameters) - */ -uint32_t br_rsa_i62_keygen( - const br_prng_class **rng_ctx, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp); - -/** - * \brief Get the RSA "i62" implementation (key pair generation), - * if available. - * - * \return the implementation, or 0. - */ -br_rsa_keygen br_rsa_i62_keygen_get(void); - -/** - * \brief Get "default" RSA implementation (key pair generation). - * - * This returns the preferred implementation of RSA (key pair generation) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_keygen br_rsa_keygen_get_default(void); - -/** - * \brief Type for a modulus computing function. - * - * Such a function computes the public modulus from the private key. The - * encoded modulus (unsigned big-endian) is written on `n`, and the size - * (in bytes) is returned. If `n` is `NULL`, then the size is returned but - * the modulus itself is not computed. - * - * If the key size exceeds an internal limit, 0 is returned. - * - * \param n destination buffer (or `NULL`). - * \param sk RSA private key. - * \return the modulus length (in bytes), or 0. - */ -typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk); - -/** - * \brief Recompute RSA modulus ("i15" engine). - * - * \see br_rsa_compute_modulus - * - * \param n destination buffer (or `NULL`). - * \param sk RSA private key. - * \return the modulus length (in bytes), or 0. - */ -size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk); - -/** - * \brief Recompute RSA modulus ("i31" engine). - * - * \see br_rsa_compute_modulus - * - * \param n destination buffer (or `NULL`). - * \param sk RSA private key. - * \return the modulus length (in bytes), or 0. - */ -size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk); - -/** - * \brief Get "default" RSA implementation (recompute modulus). - * - * This returns the preferred implementation of RSA (recompute modulus) - * on the current system. - * - * \return the default implementation. - */ -br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void); - -/** - * \brief Type for a public exponent computing function. - * - * Such a function recomputes the public exponent from the private key. - * 0 is returned if any of the following occurs: - * - * - Either `p` or `q` is not equal to 3 modulo 4. - * - * - The public exponent does not fit on 32 bits. - * - * - An internal limit is exceeded. - * - * - The private key is invalid in some way. - * - * For all private keys produced by the key generator functions - * (`br_rsa_keygen` type), this function succeeds and returns the true - * public exponent. The public exponent is always an odd integer greater - * than 1. - * - * \return the public exponent, or 0. - */ -typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk); - -/** - * \brief Recompute RSA public exponent ("i15" engine). - * - * \see br_rsa_compute_pubexp - * - * \return the public exponent, or 0. - */ -uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk); - -/** - * \brief Recompute RSA public exponent ("i31" engine). - * - * \see br_rsa_compute_pubexp - * - * \return the public exponent, or 0. - */ -uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk); - -/** - * \brief Get "default" RSA implementation (recompute public exponent). - * - * This returns the preferred implementation of RSA (recompute public - * exponent) on the current system. - * - * \return the default implementation. - */ -br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void); - -/** - * \brief Type for a private exponent computing function. - * - * An RSA private key (`br_rsa_private_key`) contains two reduced - * private exponents, which are sufficient to perform private key - * operations. However, standard encoding formats for RSA private keys - * require also a copy of the complete private exponent (non-reduced), - * which this function recomputes. - * - * This function succeeds if all the following conditions hold: - * - * - Both private factors `p` and `q` are equal to 3 modulo 4. - * - * - The provided public exponent `pubexp` is correct, and, in particular, - * is odd, relatively prime to `p-1` and `q-1`, and greater than 1. - * - * - No internal storage limit is exceeded. - * - * For all private keys produced by the key generator functions - * (`br_rsa_keygen` type), this function succeeds. Note that the API - * restricts the public exponent to a maximum size of 32 bits. - * - * The encoded private exponent is written in `d` (unsigned big-endian - * convention), and the length (in bytes) is returned. If `d` is `NULL`, - * then the exponent is not written anywhere, but the length is still - * returned. On error, 0 is returned. - * - * Not all error conditions are detected when `d` is `NULL`; therefore, the - * returned value shall be checked also when actually producing the value. - * - * \param d destination buffer (or `NULL`). - * \param sk RSA private key. - * \param pubexp the public exponent. - * \return the private exponent length (in bytes), or 0. - */ -typedef size_t (*br_rsa_compute_privexp)(void *d, - const br_rsa_private_key *sk, uint32_t pubexp); - -/** - * \brief Recompute RSA private exponent ("i15" engine). - * - * \see br_rsa_compute_privexp - * - * \param d destination buffer (or `NULL`). - * \param sk RSA private key. - * \param pubexp the public exponent. - * \return the private exponent length (in bytes), or 0. - */ -size_t br_rsa_i15_compute_privexp(void *d, - const br_rsa_private_key *sk, uint32_t pubexp); - -/** - * \brief Recompute RSA private exponent ("i31" engine). - * - * \see br_rsa_compute_privexp - * - * \param d destination buffer (or `NULL`). - * \param sk RSA private key. - * \param pubexp the public exponent. - * \return the private exponent length (in bytes), or 0. - */ -size_t br_rsa_i31_compute_privexp(void *d, - const br_rsa_private_key *sk, uint32_t pubexp); - -/** - * \brief Get "default" RSA implementation (recompute private exponent). - * - * This returns the preferred implementation of RSA (recompute private - * exponent) on the current system. - * - * \return the default implementation. - */ -br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_ssl.h b/src/tls/bearssl/bearssl_ssl.h deleted file mode 100644 index a603fdbe8..000000000 --- a/src/tls/bearssl/bearssl_ssl.h +++ /dev/null @@ -1,4301 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_SSL_H__ -#define BR_BEARSSL_SSL_H__ - -#include -#include - -#include "bearssl_block.h" -#include "bearssl_hash.h" -#include "bearssl_hmac.h" -#include "bearssl_prf.h" -#include "bearssl_rand.h" -#include "bearssl_x509.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_ssl.h - * - * # SSL - * - * For an overview of the SSL/TLS API, see [the BearSSL Web - * site](https://www.bearssl.org/api1.html). - * - * The `BR_TLS_*` constants correspond to the standard cipher suites and - * their values in the [IANA - * registry](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4). - * - * The `BR_ALERT_*` constants are for standard TLS alert messages. When - * a fatal alert message is sent of received, then the SSL engine context - * status is set to the sum of that alert value (an integer in the 0..255 - * range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert, - * `BR_ERR_RECV_FATAL_ALERT` for a received alert). - */ - -/** \brief Optimal input buffer size. */ -#define BR_SSL_BUFSIZE_INPUT (16384 + 325) - -/** \brief Optimal output buffer size. */ -#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85) - -/** \brief Optimal buffer size for monodirectional engine - (shared input/output buffer). */ -#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT - -/** \brief Optimal buffer size for bidirectional engine - (single buffer split into two separate input/output buffers). */ -#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT) - -/* - * Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1 - * and TLS 1.2). Note that though there is a constant for SSL 3.0, that - * protocol version is not actually supported. - */ - -/** \brief Protocol version: SSL 3.0 (unsupported). */ -#define BR_SSL30 0x0300 -/** \brief Protocol version: TLS 1.0. */ -#define BR_TLS10 0x0301 -/** \brief Protocol version: TLS 1.1. */ -#define BR_TLS11 0x0302 -/** \brief Protocol version: TLS 1.2. */ -#define BR_TLS12 0x0303 - -/* - * Error constants. They are used to report the reason why a context has - * been marked as failed. - * - * Implementation note: SSL-level error codes should be in the 1..31 - * range. The 32..63 range is for certificate decoding and validation - * errors. Received fatal alerts imply an error code in the 256..511 range. - */ - -/** \brief SSL status: no error so far (0). */ -#define BR_ERR_OK 0 - -/** \brief SSL status: caller-provided parameter is incorrect. */ -#define BR_ERR_BAD_PARAM 1 - -/** \brief SSL status: operation requested by the caller cannot be applied - with the current context state (e.g. reading data while outgoing data - is waiting to be sent). */ -#define BR_ERR_BAD_STATE 2 - -/** \brief SSL status: incoming protocol or record version is unsupported. */ -#define BR_ERR_UNSUPPORTED_VERSION 3 - -/** \brief SSL status: incoming record version does not match the expected - version. */ -#define BR_ERR_BAD_VERSION 4 - -/** \brief SSL status: incoming record length is invalid. */ -#define BR_ERR_BAD_LENGTH 5 - -/** \brief SSL status: incoming record is too large to be processed, or - buffer is too small for the handshake message to send. */ -#define BR_ERR_TOO_LARGE 6 - -/** \brief SSL status: decryption found an invalid padding, or the record - MAC is not correct. */ -#define BR_ERR_BAD_MAC 7 - -/** \brief SSL status: no initial entropy was provided, and none can be - obtained from the OS. */ -#define BR_ERR_NO_RANDOM 8 - -/** \brief SSL status: incoming record type is unknown. */ -#define BR_ERR_UNKNOWN_TYPE 9 - -/** \brief SSL status: incoming record or message has wrong type with - regards to the current engine state. */ -#define BR_ERR_UNEXPECTED 10 - -/** \brief SSL status: ChangeCipherSpec message from the peer has invalid - contents. */ -#define BR_ERR_BAD_CCS 12 - -/** \brief SSL status: alert message from the peer has invalid contents - (odd length). */ -#define BR_ERR_BAD_ALERT 13 - -/** \brief SSL status: incoming handshake message decoding failed. */ -#define BR_ERR_BAD_HANDSHAKE 14 - -/** \brief SSL status: ServerHello contains a session ID which is larger - than 32 bytes. */ -#define BR_ERR_OVERSIZED_ID 15 - -/** \brief SSL status: server wants to use a cipher suite that we did - not claim to support. This is also reported if we tried to advertise - a cipher suite that we do not support. */ -#define BR_ERR_BAD_CIPHER_SUITE 16 - -/** \brief SSL status: server wants to use a compression that we did not - claim to support. */ -#define BR_ERR_BAD_COMPRESSION 17 - -/** \brief SSL status: server's max fragment length does not match - client's. */ -#define BR_ERR_BAD_FRAGLEN 18 - -/** \brief SSL status: secure renegotiation failed. */ -#define BR_ERR_BAD_SECRENEG 19 - -/** \brief SSL status: server sent an extension type that we did not - announce, or used the same extension type several times in a single - ServerHello. */ -#define BR_ERR_EXTRA_EXTENSION 20 - -/** \brief SSL status: invalid Server Name Indication contents (when - used by the server, this extension shall be empty). */ -#define BR_ERR_BAD_SNI 21 - -/** \brief SSL status: invalid ServerHelloDone from the server (length - is not 0). */ -#define BR_ERR_BAD_HELLO_DONE 22 - -/** \brief SSL status: internal limit exceeded (e.g. server's public key - is too large). */ -#define BR_ERR_LIMIT_EXCEEDED 23 - -/** \brief SSL status: Finished message from peer does not match the - expected value. */ -#define BR_ERR_BAD_FINISHED 24 - -/** \brief SSL status: session resumption attempt with distinct version - or cipher suite. */ -#define BR_ERR_RESUME_MISMATCH 25 - -/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve, - signature algorithm, hash function). */ -#define BR_ERR_INVALID_ALGORITHM 26 - -/** \brief SSL status: invalid signature (on ServerKeyExchange from - server, or in CertificateVerify from client). */ -#define BR_ERR_BAD_SIGNATURE 27 - -/** \brief SSL status: peer's public key does not have the proper type - or is not allowed for requested operation. */ -#define BR_ERR_WRONG_KEY_USAGE 28 - -/** \brief SSL status: client did not send a certificate upon request, - or the client certificate could not be validated. */ -#define BR_ERR_NO_CLIENT_AUTH 29 - -/** \brief SSL status: I/O error or premature close on underlying - transport stream. This error code is set only by the simplified - I/O API ("br_sslio_*"). */ -#define BR_ERR_IO 31 - -/** \brief SSL status: base value for a received fatal alert. - - When a fatal alert is received from the peer, the alert value - is added to this constant. */ -#define BR_ERR_RECV_FATAL_ALERT 256 - -/** \brief SSL status: base value for a sent fatal alert. - - When a fatal alert is sent to the peer, the alert value is added - to this constant. */ -#define BR_ERR_SEND_FATAL_ALERT 512 - -/* ===================================================================== */ - -/** - * \brief Decryption engine for SSL. - * - * When processing incoming records, the SSL engine will use a decryption - * engine that uses a specific context structure, and has a set of - * methods (a vtable) that follows this template. - * - * The decryption engine is responsible for applying decryption, verifying - * MAC, and keeping track of the record sequence number. - */ -typedef struct br_sslrec_in_class_ br_sslrec_in_class; -struct br_sslrec_in_class_ { - /** - * \brief Context size (in bytes). - */ - size_t context_size; - - /** - * \brief Test validity of the incoming record length. - * - * This function returns 1 if the announced length for an - * incoming record is valid, 0 otherwise, - * - * \param ctx decryption engine context. - * \param record_len incoming record length. - * \return 1 of a valid length, 0 otherwise. - */ - int (*check_length)(const br_sslrec_in_class *const *ctx, - size_t record_len); - - /** - * \brief Decrypt the incoming record. - * - * This function may assume that the record length is valid - * (it has been previously tested with `check_length()`). - * Decryption is done in place; `*len` is updated with the - * cleartext length, and the address of the first plaintext - * byte is returned. If the record is correct but empty, then - * `*len` is set to 0 and a non-`NULL` pointer is returned. - * - * On decryption/MAC error, `NULL` is returned. - * - * \param ctx decryption engine context. - * \param record_type record type (23 for application data, etc). - * \param version record version. - * \param payload address of encrypted payload. - * \param len pointer to payload length (updated). - * \return pointer to plaintext, or `NULL` on error. - */ - unsigned char *(*decrypt)(const br_sslrec_in_class **ctx, - int record_type, unsigned version, - void *payload, size_t *len); -}; - -/** - * \brief Encryption engine for SSL. - * - * When building outgoing records, the SSL engine will use an encryption - * engine that uses a specific context structure, and has a set of - * methods (a vtable) that follows this template. - * - * The encryption engine is responsible for applying encryption and MAC, - * and keeping track of the record sequence number. - */ -typedef struct br_sslrec_out_class_ br_sslrec_out_class; -struct br_sslrec_out_class_ { - /** - * \brief Context size (in bytes). - */ - size_t context_size; - - /** - * \brief Compute maximum plaintext sizes and offsets. - * - * When this function is called, the `*start` and `*end` - * values contain offsets designating the free area in the - * outgoing buffer for plaintext data; that free area is - * preceded by a 5-byte space which will receive the record - * header. - * - * The `max_plaintext()` function is responsible for adjusting - * both `*start` and `*end` to make room for any record-specific - * header, MAC, padding, and possible split. - * - * \param ctx encryption engine context. - * \param start pointer to start of plaintext offset (updated). - * \param end pointer to start of plaintext offset (updated). - */ - void (*max_plaintext)(const br_sslrec_out_class *const *ctx, - size_t *start, size_t *end); - - /** - * \brief Perform record encryption. - * - * This function encrypts the record. The plaintext address and - * length are provided. Returned value is the start of the - * encrypted record (or sequence of records, if a split was - * performed), _including_ the 5-byte header, and `*len` is - * adjusted to the total size of the record(s), there again - * including the header(s). - * - * \param ctx decryption engine context. - * \param record_type record type (23 for application data, etc). - * \param version record version. - * \param plaintext address of plaintext. - * \param len pointer to plaintext length (updated). - * \return pointer to start of built record. - */ - unsigned char *(*encrypt)(const br_sslrec_out_class **ctx, - int record_type, unsigned version, - void *plaintext, size_t *len); -}; - -/** - * \brief Context for a no-encryption engine. - * - * The no-encryption engine processes outgoing records during the initial - * handshake, before encryption is applied. - */ -typedef struct { - /** \brief No-encryption engine vtable. */ - const br_sslrec_out_class *vtable; -} br_sslrec_out_clear_context; - -/** \brief Static, constant vtable for the no-encryption engine. */ -extern const br_sslrec_out_class br_sslrec_out_clear_vtable; - -/* ===================================================================== */ - -/** - * \brief Record decryption engine class, for CBC mode. - * - * This class type extends the decryption engine class with an - * initialisation method that receives the parameters needed - * for CBC processing: block cipher implementation, block cipher key, - * HMAC parameters (hash function, key, MAC length), and IV. If the - * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). - */ -typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class; -struct br_sslrec_in_cbc_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_in_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CBC decryption). - * \param bc_key block cipher key. - * \param bc_key_len block cipher key length (in bytes). - * \param dig_impl hash function for HMAC. - * \param mac_key HMAC key. - * \param mac_key_len HMAC key length (in bytes). - * \param mac_out_len HMAC output length (in bytes). - * \param iv initial IV (or `NULL`). - */ - void (*init)(const br_sslrec_in_cbc_class **ctx, - const br_block_cbcdec_class *bc_impl, - const void *bc_key, size_t bc_key_len, - const br_hash_class *dig_impl, - const void *mac_key, size_t mac_key_len, size_t mac_out_len, - const void *iv); -}; - -/** - * \brief Record encryption engine class, for CBC mode. - * - * This class type extends the encryption engine class with an - * initialisation method that receives the parameters needed - * for CBC processing: block cipher implementation, block cipher key, - * HMAC parameters (hash function, key, MAC length), and IV. If the - * IV is `NULL`, then a per-record IV will be used (TLS 1.1+). - */ -typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class; -struct br_sslrec_out_cbc_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_out_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CBC encryption). - * \param bc_key block cipher key. - * \param bc_key_len block cipher key length (in bytes). - * \param dig_impl hash function for HMAC. - * \param mac_key HMAC key. - * \param mac_key_len HMAC key length (in bytes). - * \param mac_out_len HMAC output length (in bytes). - * \param iv initial IV (or `NULL`). - */ - void (*init)(const br_sslrec_out_cbc_class **ctx, - const br_block_cbcenc_class *bc_impl, - const void *bc_key, size_t bc_key_len, - const br_hash_class *dig_impl, - const void *mac_key, size_t mac_key_len, size_t mac_out_len, - const void *iv); -}; - -/** - * \brief Context structure for decrypting incoming records with - * CBC + HMAC. - * - * The first field points to the vtable. The other fields are opaque - * and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_sslrec_in_cbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t seq; - union { - const br_block_cbcdec_class *vtable; - br_aes_gen_cbcdec_keys aes; - br_des_gen_cbcdec_keys des; - } bc; - br_hmac_key_context mac; - size_t mac_len; - unsigned char iv[16]; - int explicit_IV; -#endif -} br_sslrec_in_cbc_context; - -/** - * \brief Static, constant vtable for record decryption with CBC. - */ -extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable; - -/** - * \brief Context structure for encrypting outgoing records with - * CBC + HMAC. - * - * The first field points to the vtable. The other fields are opaque - * and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_sslrec_out_cbc_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t seq; - union { - const br_block_cbcenc_class *vtable; - br_aes_gen_cbcenc_keys aes; - br_des_gen_cbcenc_keys des; - } bc; - br_hmac_key_context mac; - size_t mac_len; - unsigned char iv[16]; - int explicit_IV; -#endif -} br_sslrec_out_cbc_context; - -/** - * \brief Static, constant vtable for record encryption with CBC. - */ -extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable; - -/* ===================================================================== */ - -/** - * \brief Record decryption engine class, for GCM mode. - * - * This class type extends the decryption engine class with an - * initialisation method that receives the parameters needed - * for GCM processing: block cipher implementation, block cipher key, - * GHASH implementation, and 4-byte IV. - */ -typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class; -struct br_sslrec_in_gcm_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_in_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CTR). - * \param key block cipher key. - * \param key_len block cipher key length (in bytes). - * \param gh_impl GHASH implementation. - * \param iv static IV (4 bytes). - */ - void (*init)(const br_sslrec_in_gcm_class **ctx, - const br_block_ctr_class *bc_impl, - const void *key, size_t key_len, - br_ghash gh_impl, - const void *iv); -}; - -/** - * \brief Record encryption engine class, for GCM mode. - * - * This class type extends the encryption engine class with an - * initialisation method that receives the parameters needed - * for GCM processing: block cipher implementation, block cipher key, - * GHASH implementation, and 4-byte IV. - */ -typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class; -struct br_sslrec_out_gcm_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_out_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CTR). - * \param key block cipher key. - * \param key_len block cipher key length (in bytes). - * \param gh_impl GHASH implementation. - * \param iv static IV (4 bytes). - */ - void (*init)(const br_sslrec_out_gcm_class **ctx, - const br_block_ctr_class *bc_impl, - const void *key, size_t key_len, - br_ghash gh_impl, - const void *iv); -}; - -/** - * \brief Context structure for processing records with GCM. - * - * The same context structure is used for encrypting and decrypting. - * - * The first field points to the vtable. The other fields are opaque - * and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - union { - const void *gen; - const br_sslrec_in_gcm_class *in; - const br_sslrec_out_gcm_class *out; - } vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t seq; - union { - const br_block_ctr_class *vtable; - br_aes_gen_ctr_keys aes; - } bc; - br_ghash gh; - unsigned char iv[4]; - unsigned char h[16]; -#endif -} br_sslrec_gcm_context; - -/** - * \brief Static, constant vtable for record decryption with GCM. - */ -extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable; - -/** - * \brief Static, constant vtable for record encryption with GCM. - */ -extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable; - -/* ===================================================================== */ - -/** - * \brief Record decryption engine class, for ChaCha20+Poly1305. - * - * This class type extends the decryption engine class with an - * initialisation method that receives the parameters needed - * for ChaCha20+Poly1305 processing: ChaCha20 implementation, - * Poly1305 implementation, key, and 12-byte IV. - */ -typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class; -struct br_sslrec_in_chapol_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_in_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param ichacha ChaCha20 implementation. - * \param ipoly Poly1305 implementation. - * \param key secret key (32 bytes). - * \param iv static IV (12 bytes). - */ - void (*init)(const br_sslrec_in_chapol_class **ctx, - br_chacha20_run ichacha, - br_poly1305_run ipoly, - const void *key, const void *iv); -}; - -/** - * \brief Record encryption engine class, for ChaCha20+Poly1305. - * - * This class type extends the encryption engine class with an - * initialisation method that receives the parameters needed - * for ChaCha20+Poly1305 processing: ChaCha20 implementation, - * Poly1305 implementation, key, and 12-byte IV. - */ -typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class; -struct br_sslrec_out_chapol_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_out_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param ichacha ChaCha20 implementation. - * \param ipoly Poly1305 implementation. - * \param key secret key (32 bytes). - * \param iv static IV (12 bytes). - */ - void (*init)(const br_sslrec_out_chapol_class **ctx, - br_chacha20_run ichacha, - br_poly1305_run ipoly, - const void *key, const void *iv); -}; - -/** - * \brief Context structure for processing records with ChaCha20+Poly1305. - * - * The same context structure is used for encrypting and decrypting. - * - * The first field points to the vtable. The other fields are opaque - * and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - union { - const void *gen; - const br_sslrec_in_chapol_class *in; - const br_sslrec_out_chapol_class *out; - } vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t seq; - unsigned char key[32]; - unsigned char iv[12]; - br_chacha20_run ichacha; - br_poly1305_run ipoly; -#endif -} br_sslrec_chapol_context; - -/** - * \brief Static, constant vtable for record decryption with ChaCha20+Poly1305. - */ -extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable; - -/** - * \brief Static, constant vtable for record encryption with ChaCha20+Poly1305. - */ -extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable; - -/* ===================================================================== */ - -/** - * \brief Record decryption engine class, for CCM mode. - * - * This class type extends the decryption engine class with an - * initialisation method that receives the parameters needed - * for CCM processing: block cipher implementation, block cipher key, - * and 4-byte IV. - */ -typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class; -struct br_sslrec_in_ccm_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_in_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CTR+CBC). - * \param key block cipher key. - * \param key_len block cipher key length (in bytes). - * \param iv static IV (4 bytes). - * \param tag_len tag length (in bytes) - */ - void (*init)(const br_sslrec_in_ccm_class **ctx, - const br_block_ctrcbc_class *bc_impl, - const void *key, size_t key_len, - const void *iv, size_t tag_len); -}; - -/** - * \brief Record encryption engine class, for CCM mode. - * - * This class type extends the encryption engine class with an - * initialisation method that receives the parameters needed - * for CCM processing: block cipher implementation, block cipher key, - * and 4-byte IV. - */ -typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class; -struct br_sslrec_out_ccm_class_ { - /** - * \brief Superclass, as first vtable field. - */ - br_sslrec_out_class inner; - - /** - * \brief Engine initialisation method. - * - * This method sets the vtable field in the context. - * - * \param ctx context to initialise. - * \param bc_impl block cipher implementation (CTR+CBC). - * \param key block cipher key. - * \param key_len block cipher key length (in bytes). - * \param iv static IV (4 bytes). - * \param tag_len tag length (in bytes) - */ - void (*init)(const br_sslrec_out_ccm_class **ctx, - const br_block_ctrcbc_class *bc_impl, - const void *key, size_t key_len, - const void *iv, size_t tag_len); -}; - -/** - * \brief Context structure for processing records with CCM. - * - * The same context structure is used for encrypting and decrypting. - * - * The first field points to the vtable. The other fields are opaque - * and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - union { - const void *gen; - const br_sslrec_in_ccm_class *in; - const br_sslrec_out_ccm_class *out; - } vtable; -#ifndef BR_DOXYGEN_IGNORE - uint64_t seq; - union { - const br_block_ctrcbc_class *vtable; - br_aes_gen_ctrcbc_keys aes; - } bc; - unsigned char iv[4]; - size_t tag_len; -#endif -} br_sslrec_ccm_context; - -/** - * \brief Static, constant vtable for record decryption with CCM. - */ -extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable; - -/** - * \brief Static, constant vtable for record encryption with CCM. - */ -extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable; - -/* ===================================================================== */ - -/** - * \brief Type for session parameters, to be saved for session resumption. - */ -typedef struct { - /** \brief Session ID buffer. */ - unsigned char session_id[32]; - /** \brief Session ID length (in bytes, at most 32). */ - unsigned char session_id_len; - /** \brief Protocol version. */ - uint16_t version; - /** \brief Cipher suite. */ - uint16_t cipher_suite; - /** \brief Master secret. */ - unsigned char master_secret[48]; -} br_ssl_session_parameters; - -#ifndef BR_DOXYGEN_IGNORE -/* - * Maximum number of cipher suites supported by a client or server. - */ -#define BR_MAX_CIPHER_SUITES 48 -#endif - -/** - * \brief Context structure for SSL engine. - * - * This structure is common to the client and server; both the client - * context (`br_ssl_client_context`) and the server context - * (`br_ssl_server_context`) include a `br_ssl_engine_context` as their - * first field. - * - * The engine context manages records, including alerts, closures, and - * transitions to new encryption/MAC algorithms. Processing of handshake - * records is delegated to externally provided code. This structure - * should not be used directly. - * - * Structure contents are opaque and shall not be accessed directly. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - /* - * The error code. When non-zero, then the state is "failed" and - * no I/O may occur until reset. - */ - int err; - - /* - * Configured I/O buffers. They are either disjoint, or identical. - */ - unsigned char *ibuf, *obuf; - size_t ibuf_len, obuf_len; - - /* - * Maximum fragment length applies to outgoing records; incoming - * records can be processed as long as they fit in the input - * buffer. It is guaranteed that incoming records at least as big - * as max_frag_len can be processed. - */ - uint16_t max_frag_len; - unsigned char log_max_frag_len; - unsigned char peer_log_max_frag_len; - - /* - * Buffering management registers. - */ - size_t ixa, ixb, ixc; - size_t oxa, oxb, oxc; - unsigned char iomode; - unsigned char incrypt; - - /* - * Shutdown flag: when set to non-zero, incoming record bytes - * will not be accepted anymore. This is used after a close_notify - * has been received: afterwards, the engine no longer claims that - * it could receive bytes from the transport medium. - */ - unsigned char shutdown_recv; - - /* - * 'record_type_in' is set to the incoming record type when the - * record header has been received. - * 'record_type_out' is used to make the next outgoing record - * header when it is ready to go. - */ - unsigned char record_type_in, record_type_out; - - /* - * When a record is received, its version is extracted: - * -- if 'version_in' is 0, then it is set to the received version; - * -- otherwise, if the received version is not identical to - * the 'version_in' contents, then a failure is reported. - * - * This implements the SSL requirement that all records shall - * use the negotiated protocol version, once decided (in the - * ServerHello). It is up to the handshake handler to adjust this - * field when necessary. - */ - uint16_t version_in; - - /* - * 'version_out' is used when the next outgoing record is ready - * to go. - */ - uint16_t version_out; - - /* - * Record handler contexts. - */ - union { - const br_sslrec_in_class *vtable; - br_sslrec_in_cbc_context cbc; - br_sslrec_gcm_context gcm; - br_sslrec_chapol_context chapol; - br_sslrec_ccm_context ccm; - } in; - union { - const br_sslrec_out_class *vtable; - br_sslrec_out_clear_context clear; - br_sslrec_out_cbc_context cbc; - br_sslrec_gcm_context gcm; - br_sslrec_chapol_context chapol; - br_sslrec_ccm_context ccm; - } out; - - /* - * The "application data" flag. Value: - * 0 handshake is in process, no application data acceptable - * 1 application data can be sent and received - * 2 closing, no application data can be sent, but some - * can still be received (and discarded) - */ - unsigned char application_data; - - /* - * Context RNG. - * - * rng_init_done is initially 0. It is set to 1 when the - * basic structure of the RNG is set, and 2 when some - * entropy has been pushed in. The value 2 marks the RNG - * as "properly seeded". - * - * rng_os_rand_done is initially 0. It is set to 1 when - * some seeding from the OS or hardware has been attempted. - */ - br_hmac_drbg_context rng; - int rng_init_done; - int rng_os_rand_done; - - /* - * Supported minimum and maximum versions, and cipher suites. - */ - uint16_t version_min; - uint16_t version_max; - uint16_t suites_buf[BR_MAX_CIPHER_SUITES]; - unsigned char suites_num; - - /* - * For clients, the server name to send as a SNI extension. For - * servers, the name received in the SNI extension (if any). - */ - char server_name[256]; - - /* - * "Security parameters". These are filled by the handshake - * handler, and used when switching encryption state. - */ - unsigned char client_random[32]; - unsigned char server_random[32]; - br_ssl_session_parameters session; - - /* - * ECDHE elements: curve and point from the peer. The server also - * uses that buffer for the point to send to the client. - */ - unsigned char ecdhe_curve; - unsigned char ecdhe_point[133]; - unsigned char ecdhe_point_len; - - /* - * Secure renegotiation (RFC 5746): 'reneg' can be: - * 0 first handshake (server support is not known) - * 1 peer does not support secure renegotiation - * 2 peer supports secure renegotiation - * - * The saved_finished buffer contains the client and the - * server "Finished" values from the last handshake, in - * that order (12 bytes each). - */ - unsigned char reneg; - unsigned char saved_finished[24]; - - /* - * Behavioural flags. - */ - uint32_t flags; - - /* - * Context variables for the handshake processor. The 'pad' must - * be large enough to accommodate an RSA-encrypted pre-master - * secret, or an RSA signature; since we want to support up to - * RSA-4096, this means at least 512 bytes. (Other pad usages - * require its length to be at least 256.) - */ - struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; - } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; - unsigned char pad[512]; - unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out; - size_t hlen_in, hlen_out; - void (*hsrun)(void *ctx); - - /* - * The 'action' value communicates OOB information between the - * engine and the handshake processor. - * - * From the engine: - * 0 invocation triggered by I/O - * 1 invocation triggered by explicit close - * 2 invocation triggered by explicit renegotiation - */ - unsigned char action; - - /* - * State for alert messages. Value is either 0, or the value of - * the alert level byte (level is either 1 for warning, or 2 for - * fatal; we convert all other values to 'fatal'). - */ - unsigned char alert; - - /* - * Closure flags. This flag is set when a close_notify has been - * received from the peer. - */ - unsigned char close_received; - - /* - * Multi-hasher for the handshake messages. The handshake handler - * is responsible for resetting it when appropriate. - */ - br_multihash_context mhash; - - /* - * Pointer to the X.509 engine. The engine is supposed to be - * already initialized. It is used to validate the peer's - * certificate. - */ - const br_x509_class **x509ctx; - - /* - * Certificate chain to send. This is used by both client and - * server, when they send their respective Certificate messages. - * If chain_len is 0, then chain may be NULL. - */ - const br_x509_certificate *chain; - size_t chain_len; - const unsigned char *cert_cur; - size_t cert_len; - - /* - * List of supported protocol names (ALPN extension). If unset, - * (number of names is 0), then: - * - the client sends no ALPN extension; - * - the server ignores any incoming ALPN extension. - * - * Otherwise: - * - the client sends an ALPN extension with all the names; - * - the server selects the first protocol in its list that - * the client also supports, or fails (fatal alert 120) - * if the client sends an ALPN extension and there is no - * match. - * - * The 'selected_protocol' field contains 1+n if the matching - * name has index n in the list (the value is 0 if no match was - * performed, e.g. the peer did not send an ALPN extension). - */ - const char **protocol_names; - uint16_t protocol_names_num; - uint16_t selected_protocol; - - /* - * Pointers to implementations; left to NULL for unsupported - * functions. For the raw hash functions, implementations are - * referenced from the multihasher (mhash field). - */ - br_tls_prf_impl prf10; - br_tls_prf_impl prf_sha256; - br_tls_prf_impl prf_sha384; - const br_block_cbcenc_class *iaes_cbcenc; - const br_block_cbcdec_class *iaes_cbcdec; - const br_block_ctr_class *iaes_ctr; - const br_block_ctrcbc_class *iaes_ctrcbc; - const br_block_cbcenc_class *ides_cbcenc; - const br_block_cbcdec_class *ides_cbcdec; - br_ghash ighash; - br_chacha20_run ichacha; - br_poly1305_run ipoly; - const br_sslrec_in_cbc_class *icbc_in; - const br_sslrec_out_cbc_class *icbc_out; - const br_sslrec_in_gcm_class *igcm_in; - const br_sslrec_out_gcm_class *igcm_out; - const br_sslrec_in_chapol_class *ichapol_in; - const br_sslrec_out_chapol_class *ichapol_out; - const br_sslrec_in_ccm_class *iccm_in; - const br_sslrec_out_ccm_class *iccm_out; - const br_ec_impl *iec; - br_rsa_pkcs1_vrfy irsavrfy; - br_ecdsa_vrfy iecdsa; -#endif -} br_ssl_engine_context; - -/** - * \brief Get currently defined engine behavioural flags. - * - * \param cc SSL engine context. - * \return the flags. - */ -static inline uint32_t -br_ssl_engine_get_flags(br_ssl_engine_context *cc) -{ - return cc->flags; -} - -/** - * \brief Set all engine behavioural flags. - * - * \param cc SSL engine context. - * \param flags new value for all flags. - */ -static inline void -br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags) -{ - cc->flags = flags; -} - -/** - * \brief Set some engine behavioural flags. - * - * The flags set in the `flags` parameter are set in the context; other - * flags are untouched. - * - * \param cc SSL engine context. - * \param flags additional set flags. - */ -static inline void -br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags) -{ - cc->flags |= flags; -} - -/** - * \brief Clear some engine behavioural flags. - * - * The flags set in the `flags` parameter are cleared from the context; other - * flags are untouched. - * - * \param cc SSL engine context. - * \param flags flags to remove. - */ -static inline void -br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags) -{ - cc->flags &= ~flags; -} - -/** - * \brief Behavioural flag: enforce server preferences. - * - * If this flag is set, then the server will enforce its own cipher suite - * preference order; otherwise, it follows the client preferences. - */ -#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0) - -/** - * \brief Behavioural flag: disable renegotiation. - * - * If this flag is set, then renegotiations are rejected unconditionally: - * they won't be honoured if asked for programmatically, and requests from - * the peer are rejected. - */ -#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1) - -/** - * \brief Behavioural flag: tolerate lack of client authentication. - * - * If this flag is set in a server and the server requests a client - * certificate, but the authentication fails (the client does not send - * a certificate, or the client's certificate chain cannot be validated), - * then the connection keeps on. Without this flag, a failed client - * authentication terminates the connection. - * - * Notes: - * - * - If the client's certificate can be validated and its public key is - * supported, then a wrong signature value terminates the connection - * regardless of that flag. - * - * - If using full-static ECDH, then a failure to validate the client's - * certificate prevents the handshake from succeeding. - */ -#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2) - -/** - * \brief Behavioural flag: fail on application protocol mismatch. - * - * The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301)) - * allows the client to send a list of application protocol names, and - * the server to select one. A mismatch is one of the following occurrences: - * - * - On the client: the client sends a list of names, the server - * responds with a protocol name which is _not_ part of the list of - * names sent by the client. - * - * - On the server: the client sends a list of names, and the server - * is also configured with a list of names, but there is no common - * protocol name between the two lists. - * - * Normal behaviour in case of mismatch is to report no matching name - * (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on. - * If the flag is set, then a mismatch implies a protocol failure (if - * the mismatch is detected by the server, it will send a fatal alert). - * - * Note: even with this flag, `br_ssl_engine_get_selected_protocol()` - * may still return `NULL` if the client or the server does not send an - * ALPN extension at all. - */ -#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3) - -/** - * \brief Set the minimum and maximum supported protocol versions. - * - * The two provided versions MUST be supported by the implementation - * (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower - * than `version_min`. - * - * \param cc SSL engine context. - * \param version_min minimum supported TLS version. - * \param version_max maximum supported TLS version. - */ -static inline void -br_ssl_engine_set_versions(br_ssl_engine_context *cc, - unsigned version_min, unsigned version_max) -{ - cc->version_min = version_min; - cc->version_max = version_max; -} - -/** - * \brief Set the list of cipher suites advertised by this context. - * - * The provided array is copied into the context. It is the caller - * responsibility to ensure that all provided suites will be supported - * by the context. The engine context has enough room to receive _all_ - * suites supported by the implementation. The provided array MUST NOT - * contain duplicates. - * - * If the engine is for a client, the "signaling" pseudo-cipher suite - * `TLS_FALLBACK_SCSV` can be added at the end of the list, if the - * calling application is performing a voluntary downgrade (voluntary - * downgrades are not recommended, but if such a downgrade is done, then - * adding the fallback pseudo-suite is a good idea). - * - * \param cc SSL engine context. - * \param suites cipher suites. - * \param suites_num number of cipher suites. - */ -void br_ssl_engine_set_suites(br_ssl_engine_context *cc, - const uint16_t *suites, size_t suites_num); - -/** - * \brief Set the X.509 engine. - * - * The caller shall ensure that the X.509 engine is properly initialised. - * - * \param cc SSL engine context. - * \param x509ctx X.509 certificate validation context. - */ -static inline void -br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx) -{ - cc->x509ctx = x509ctx; -} - -/** - * \brief Set the supported protocol names. - * - * Protocol names are part of the ALPN extension ([RFC - * 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a - * character string, containing no more than 255 characters (256 with the - * terminating zero). When names are set, then: - * - * - The client will send an ALPN extension, containing the names. If - * the server responds with an ALPN extension, the client will verify - * that the response contains one of its name, and report that name - * through `br_ssl_engine_get_selected_protocol()`. - * - * - The server will parse incoming ALPN extension (from clients), and - * try to find a common protocol; if none is found, the connection - * is aborted with a fatal alert. On match, a response ALPN extension - * is sent, and name is reported through - * `br_ssl_engine_get_selected_protocol()`. - * - * The provided array is linked in, and must remain valid while the - * connection is live. - * - * Names MUST NOT be empty. Names MUST NOT be longer than 255 characters - * (excluding the terminating 0). - * - * \param ctx SSL engine context. - * \param names list of protocol names (zero-terminated). - * \param num number of protocol names (MUST be 1 or more). - */ -static inline void -br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx, - const char **names, size_t num) -{ - ctx->protocol_names = names; - ctx->protocol_names_num = num; -} - -/** - * \brief Get the selected protocol. - * - * If this context was initialised with a non-empty list of protocol - * names, and both client and server sent ALPN extensions during the - * handshake, and a common name was found, then that name is returned. - * Otherwise, `NULL` is returned. - * - * The returned pointer is one of the pointers provided to the context - * with `br_ssl_engine_set_protocol_names()`. - * - * \return the selected protocol, or `NULL`. - */ -static inline const char * -br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx) -{ - unsigned k; - - k = ctx->selected_protocol; - return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1]; -} - -/** - * \brief Set a hash function implementation (by ID). - * - * Hash functions set with this call will be used for SSL/TLS specific - * usages, not X.509 certificate validation. Only "standard" hash functions - * may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl` - * is `NULL`, then the hash function support is removed, not added. - * - * \param ctx SSL engine context. - * \param id hash function identifier. - * \param impl hash function implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_hash(br_ssl_engine_context *ctx, - int id, const br_hash_class *impl) -{ - br_multihash_setimpl(&ctx->mhash, id, impl); -} - -/** - * \brief Get a hash function implementation (by ID). - * - * This function retrieves a hash function implementation which was - * set with `br_ssl_engine_set_hash()`. - * - * \param ctx SSL engine context. - * \param id hash function identifier. - * \return the hash function implementation (or `NULL`). - */ -static inline const br_hash_class * -br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id) -{ - return br_multihash_getimpl(&ctx->mhash, id); -} - -/** - * \brief Set the PRF implementation (for TLS 1.0 and 1.1). - * - * This function sets (or removes, if `impl` is `NULL`) the implementation - * for the PRF used in TLS 1.0 and 1.1. - * - * \param cc SSL engine context. - * \param impl PRF implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl) -{ - cc->prf10 = impl; -} - -/** - * \brief Set the PRF implementation with SHA-256 (for TLS 1.2). - * - * This function sets (or removes, if `impl` is `NULL`) the implementation - * for the SHA-256 variant of the PRF used in TLS 1.2. - * - * \param cc SSL engine context. - * \param impl PRF implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl) -{ - cc->prf_sha256 = impl; -} - -/** - * \brief Set the PRF implementation with SHA-384 (for TLS 1.2). - * - * This function sets (or removes, if `impl` is `NULL`) the implementation - * for the SHA-384 variant of the PRF used in TLS 1.2. - * - * \param cc SSL engine context. - * \param impl PRF implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl) -{ - cc->prf_sha384 = impl; -} - -/** - * \brief Set the AES/CBC implementations. - * - * \param cc SSL engine context. - * \param impl_enc AES/CBC encryption implementation (or `NULL`). - * \param impl_dec AES/CBC decryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc, - const br_block_cbcenc_class *impl_enc, - const br_block_cbcdec_class *impl_dec) -{ - cc->iaes_cbcenc = impl_enc; - cc->iaes_cbcdec = impl_dec; -} - -/** - * \brief Set the "default" AES/CBC implementations. - * - * This function configures in the engine the AES implementations that - * should provide best runtime performance on the local system, while - * still being safe (in particular, constant-time). It also sets the - * handlers for CBC records. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc); - -/** - * \brief Set the AES/CTR implementation. - * - * \param cc SSL engine context. - * \param impl AES/CTR encryption/decryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc, - const br_block_ctr_class *impl) -{ - cc->iaes_ctr = impl; -} - -/** - * \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH). - * - * This function configures in the engine the AES/CTR and GHASH - * implementation that should provide best runtime performance on the local - * system, while still being safe (in particular, constant-time). It also - * sets the handlers for GCM records. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc); - -/** - * \brief Set the DES/CBC implementations. - * - * \param cc SSL engine context. - * \param impl_enc DES/CBC encryption implementation (or `NULL`). - * \param impl_dec DES/CBC decryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc, - const br_block_cbcenc_class *impl_enc, - const br_block_cbcdec_class *impl_dec) -{ - cc->ides_cbcenc = impl_enc; - cc->ides_cbcdec = impl_dec; -} - -/** - * \brief Set the "default" DES/CBC implementations. - * - * This function configures in the engine the DES implementations that - * should provide best runtime performance on the local system, while - * still being safe (in particular, constant-time). It also sets the - * handlers for CBC records. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc); - -/** - * \brief Set the GHASH implementation (used in GCM mode). - * - * \param cc SSL engine context. - * \param impl GHASH implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl) -{ - cc->ighash = impl; -} - -/** - * \brief Set the ChaCha20 implementation. - * - * \param cc SSL engine context. - * \param ichacha ChaCha20 implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_chacha20(br_ssl_engine_context *cc, - br_chacha20_run ichacha) -{ - cc->ichacha = ichacha; -} - -/** - * \brief Set the Poly1305 implementation. - * - * \param cc SSL engine context. - * \param ipoly Poly1305 implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_poly1305(br_ssl_engine_context *cc, - br_poly1305_run ipoly) -{ - cc->ipoly = ipoly; -} - -/** - * \brief Set the "default" ChaCha20 and Poly1305 implementations. - * - * This function configures in the engine the ChaCha20 and Poly1305 - * implementations that should provide best runtime performance on the - * local system, while still being safe (in particular, constant-time). - * It also sets the handlers for ChaCha20+Poly1305 records. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc); - -/** - * \brief Set the AES/CTR+CBC implementation. - * - * \param cc SSL engine context. - * \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc, - const br_block_ctrcbc_class *impl) -{ - cc->iaes_ctrcbc = impl; -} - -/** - * \brief Set the "default" implementations for AES/CCM. - * - * This function configures in the engine the AES/CTR+CBC - * implementation that should provide best runtime performance on the local - * system, while still being safe (in particular, constant-time). It also - * sets the handlers for CCM records. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc); - -/** - * \brief Set the record encryption and decryption engines for CBC + HMAC. - * - * \param cc SSL engine context. - * \param impl_in record CBC decryption implementation (or `NULL`). - * \param impl_out record CBC encryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_cbc(br_ssl_engine_context *cc, - const br_sslrec_in_cbc_class *impl_in, - const br_sslrec_out_cbc_class *impl_out) -{ - cc->icbc_in = impl_in; - cc->icbc_out = impl_out; -} - -/** - * \brief Set the record encryption and decryption engines for GCM. - * - * \param cc SSL engine context. - * \param impl_in record GCM decryption implementation (or `NULL`). - * \param impl_out record GCM encryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_gcm(br_ssl_engine_context *cc, - const br_sslrec_in_gcm_class *impl_in, - const br_sslrec_out_gcm_class *impl_out) -{ - cc->igcm_in = impl_in; - cc->igcm_out = impl_out; -} - -/** - * \brief Set the record encryption and decryption engines for CCM. - * - * \param cc SSL engine context. - * \param impl_in record CCM decryption implementation (or `NULL`). - * \param impl_out record CCM encryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_ccm(br_ssl_engine_context *cc, - const br_sslrec_in_ccm_class *impl_in, - const br_sslrec_out_ccm_class *impl_out) -{ - cc->iccm_in = impl_in; - cc->iccm_out = impl_out; -} - -/** - * \brief Set the record encryption and decryption engines for - * ChaCha20+Poly1305. - * - * \param cc SSL engine context. - * \param impl_in record ChaCha20 decryption implementation (or `NULL`). - * \param impl_out record ChaCha20 encryption implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_chapol(br_ssl_engine_context *cc, - const br_sslrec_in_chapol_class *impl_in, - const br_sslrec_out_chapol_class *impl_out) -{ - cc->ichapol_in = impl_in; - cc->ichapol_out = impl_out; -} - -/** - * \brief Set the EC implementation. - * - * The elliptic curve implementation will be used for ECDH and ECDHE - * cipher suites, and for ECDSA support. - * - * \param cc SSL engine context. - * \param iec EC implementation (or `NULL`). - */ -static inline void -br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec) -{ - cc->iec = iec; -} - -/** - * \brief Set the "default" EC implementation. - * - * This function sets the elliptic curve implementation for ECDH and - * ECDHE cipher suites, and for ECDSA support. It selects the fastest - * implementation on the current system. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc); - -/** - * \brief Get the EC implementation configured in the provided engine. - * - * \param cc SSL engine context. - * \return the EC implementation. - */ -static inline const br_ec_impl * -br_ssl_engine_get_ec(br_ssl_engine_context *cc) -{ - return cc->iec; -} - -/** - * \brief Set the RSA signature verification implementation. - * - * On the client, this is used to verify the server's signature on its - * ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server, - * this is used to verify the client's CertificateVerify message (if a - * client certificate is requested, and that certificate contains a RSA key). - * - * \param cc SSL engine context. - * \param irsavrfy RSA signature verification implementation. - */ -static inline void -br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy) -{ - cc->irsavrfy = irsavrfy; -} - -/** - * \brief Set the "default" RSA implementation (signature verification). - * - * This function sets the RSA implementation (signature verification) - * to the fastest implementation available on the current platform. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc); - -/** - * \brief Get the RSA implementation (signature verification) configured - * in the provided engine. - * - * \param cc SSL engine context. - * \return the RSA signature verification implementation. - */ -static inline br_rsa_pkcs1_vrfy -br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc) -{ - return cc->irsavrfy; -} - -/* - * \brief Set the ECDSA implementation (signature verification). - * - * On the client, this is used to verify the server's signature on its - * ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server, - * this is used to verify the client's CertificateVerify message (if a - * client certificate is requested, that certificate contains an EC key, - * and full-static ECDH is not used). - * - * The ECDSA implementation will use the EC core implementation configured - * in the engine context. - * - * \param cc client context. - * \param iecdsa ECDSA verification implementation. - */ -static inline void -br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa) -{ - cc->iecdsa = iecdsa; -} - -/** - * \brief Set the "default" ECDSA implementation (signature verification). - * - * This function sets the ECDSA implementation (signature verification) - * to the fastest implementation available on the current platform. This - * call also sets the elliptic curve implementation itself, there again - * to the fastest EC implementation available. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc); - -/** - * \brief Get the ECDSA implementation (signature verification) configured - * in the provided engine. - * - * \param cc SSL engine context. - * \return the ECDSA signature verification implementation. - */ -static inline br_ecdsa_vrfy -br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc) -{ - return cc->iecdsa; -} - -/** - * \brief Set the I/O buffer for the SSL engine. - * - * Once this call has been made, `br_ssl_client_reset()` or - * `br_ssl_server_reset()` MUST be called before using the context. - * - * The provided buffer will be used as long as the engine context is - * used. The caller is responsible for keeping it available. - * - * If `bidi` is 0, then the engine will operate in half-duplex mode - * (it won't be able to send data while there is unprocessed incoming - * data in the buffer, and it won't be able to receive data while there - * is unsent data in the buffer). The optimal buffer size in half-duplex - * mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra - * bytes are ignored. If the buffer is smaller, then this limits the - * capacity of the engine to support all allowed record sizes. - * - * If `bidi` is 1, then the engine will split the buffer into two - * parts, for separate handling of outgoing and incoming data. This - * enables full-duplex processing, but requires more RAM. The optimal - * buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the - * buffer is larger, then extra bytes are ignored. If the buffer is - * smaller, then the split will favour the incoming part, so that - * interoperability is maximised. - * - * \param cc SSL engine context - * \param iobuf I/O buffer. - * \param iobuf_len I/O buffer length (in bytes). - * \param bidi non-zero for full-duplex mode. - */ -void br_ssl_engine_set_buffer(br_ssl_engine_context *cc, - void *iobuf, size_t iobuf_len, int bidi); - -/** - * \brief Set the I/O buffers for the SSL engine. - * - * Once this call has been made, `br_ssl_client_reset()` or - * `br_ssl_server_reset()` MUST be called before using the context. - * - * This function is similar to `br_ssl_engine_set_buffer()`, except - * that it enforces full-duplex mode, and the two I/O buffers are - * provided as separate chunks. - * - * The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT` - * evaluate to the optimal (maximum) sizes for the input and output - * buffer, respectively. - * - * \param cc SSL engine context - * \param ibuf input buffer. - * \param ibuf_len input buffer length (in bytes). - * \param obuf output buffer. - * \param obuf_len output buffer length (in bytes). - */ -void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc, - void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len); - -/** - * \brief Inject some "initial entropy" in the context. - * - * This entropy will be added to what can be obtained from the - * underlying operating system, if that OS is supported. - * - * This function may be called several times; all injected entropy chunks - * are cumulatively mixed. - * - * If entropy gathering from the OS is supported and compiled in, then this - * step is optional. Otherwise, it is mandatory to inject randomness, and - * the caller MUST take care to push (as one or several successive calls) - * enough entropy to achieve cryptographic resistance (at least 80 bits, - * preferably 128 or more). The engine will report an error if no entropy - * was provided and none can be obtained from the OS. - * - * Take care that this function cannot assess the cryptographic quality of - * the provided bytes. - * - * In all generality, "entropy" must here be considered to mean "that - * which the attacker cannot predict". If your OS/architecture does not - * have a suitable source of randomness, then you can make do with the - * combination of a large enough secret value (possibly a copy of an - * asymmetric private key that you also store on the system) AND a - * non-repeating value (e.g. current time, provided that the local clock - * cannot be reset or altered by the attacker). - * - * \param cc SSL engine context. - * \param data extra entropy to inject. - * \param len length of the extra data (in bytes). - */ -void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, - const void *data, size_t len); - -/** - * \brief Get the "server name" in this engine. - * - * For clients, this is the name provided with `br_ssl_client_reset()`; - * for servers, this is the name received from the client as part of the - * ClientHello message. If there is no such name (e.g. the client did - * not send an SNI extension) then the returned string is empty - * (returned pointer points to a byte of value 0). - * - * The returned pointer refers to a buffer inside the context, which may - * be overwritten as part of normal SSL activity (even within the same - * connection, if a renegotiation occurs). - * - * \param cc SSL engine context. - * \return the server name (possibly empty). - */ -static inline const char * -br_ssl_engine_get_server_name(const br_ssl_engine_context *cc) -{ - return cc->server_name; -} - -/** - * \brief Get the protocol version. - * - * This function returns the protocol version that is used by the - * engine. That value is set after sending (for a server) or receiving - * (for a client) the ServerHello message. - * - * \param cc SSL engine context. - * \return the protocol version. - */ -static inline unsigned -br_ssl_engine_get_version(const br_ssl_engine_context *cc) -{ - return cc->session.version; -} - -/** - * \brief Get a copy of the session parameters. - * - * The session parameters are filled during the handshake, so this - * function shall not be called before completion of the handshake. - * The initial handshake is completed when the context first allows - * application data to be injected. - * - * This function copies the current session parameters into the provided - * structure. Beware that the session parameters include the master - * secret, which is sensitive data, to handle with great care. - * - * \param cc SSL engine context. - * \param pp destination structure for the session parameters. - */ -static inline void -br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc, - br_ssl_session_parameters *pp) -{ - memcpy(pp, &cc->session, sizeof *pp); -} - -/** - * \brief Set the session parameters to the provided values. - * - * This function is meant to be used in the client, before doing a new - * handshake; a session resumption will be attempted with these - * parameters. In the server, this function has no effect. - * - * \param cc SSL engine context. - * \param pp source structure for the session parameters. - */ -static inline void -br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc, - const br_ssl_session_parameters *pp) -{ - memcpy(&cc->session, pp, sizeof *pp); -} - -/** - * \brief Get identifier for the curve used for key exchange. - * - * If the cipher suite uses ECDHE, then this function returns the - * identifier for the curve used for transient parameters. This is - * defined during the course of the handshake, when the ServerKeyExchange - * is sent (on the server) or received (on the client). If the - * cipher suite does not use ECDHE (e.g. static ECDH, or RSA key - * exchange), then this value is indeterminate. - * - * @param cc SSL engine context. - * @return the ECDHE curve identifier. - */ -static inline int -br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc) -{ - return cc->ecdhe_curve; -} - -/** - * \brief Get the current engine state. - * - * An SSL engine (client or server) has, at any time, a state which is - * the combination of zero, one or more of these flags: - * - * - `BR_SSL_CLOSED` - * - * Engine is finished, no more I/O (until next reset). - * - * - `BR_SSL_SENDREC` - * - * Engine has some bytes to send to the peer. - * - * - `BR_SSL_RECVREC` - * - * Engine expects some bytes from the peer. - * - * - `BR_SSL_SENDAPP` - * - * Engine may receive application data to send (or flush). - * - * - `BR_SSL_RECVAPP` - * - * Engine has obtained some application data from the peer, - * that should be read by the caller. - * - * If no flag at all is set (state value is 0), then the engine is not - * fully initialised yet. - * - * The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag - * is set. To distinguish between a normal closure and an error, use - * `br_ssl_engine_last_error()`. - * - * Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually - * exclusive: the input buffer, at any point, either accumulates - * plaintext data, or contains an assembled record that is being sent. - * Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive. - * This may change in a future library version. - * - * \param cc SSL engine context. - * \return the current engine state. - */ -unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc); - -/** \brief SSL engine state: closed or failed. */ -#define BR_SSL_CLOSED 0x0001 -/** \brief SSL engine state: record data is ready to be sent to the peer. */ -#define BR_SSL_SENDREC 0x0002 -/** \brief SSL engine state: engine may receive records from the peer. */ -#define BR_SSL_RECVREC 0x0004 -/** \brief SSL engine state: engine may accept application data to send. */ -#define BR_SSL_SENDAPP 0x0008 -/** \brief SSL engine state: engine has received application data. */ -#define BR_SSL_RECVAPP 0x0010 - -/** - * \brief Get the engine error indicator. - * - * The error indicator is `BR_ERR_OK` (0) if no error was encountered - * since the last call to `br_ssl_client_reset()` or - * `br_ssl_server_reset()`. Other status values are "sticky": they - * remain set, and prevent all I/O activity, until cleared. Only the - * reset calls clear the error indicator. - * - * \param cc SSL engine context. - * \return 0, or a non-zero error code. - */ -static inline int -br_ssl_engine_last_error(const br_ssl_engine_context *cc) -{ - return cc->err; -} - -/* - * There are four I/O operations, each identified by a symbolic name: - * - * sendapp inject application data in the engine - * recvapp retrieving application data from the engine - * sendrec sending records on the transport medium - * recvrec receiving records from the transport medium - * - * Terminology works thus: in a layered model where the SSL engine sits - * between the application and the network, "send" designates operations - * where bytes flow from application to network, and "recv" for the - * reverse operation. Application data (the plaintext that is to be - * conveyed through SSL) is "app", while encrypted records are "rec". - * Note that from the SSL engine point of view, "sendapp" and "recvrec" - * designate bytes that enter the engine ("inject" operation), while - * "recvapp" and "sendrec" designate bytes that exit the engine - * ("extract" operation). - * - * For the operation 'xxx', two functions are defined: - * - * br_ssl_engine_xxx_buf - * Returns a pointer and length to the buffer to use for that - * operation. '*len' is set to the number of bytes that may be read - * from the buffer (extract operation) or written to the buffer - * (inject operation). If no byte may be exchanged for that operation - * at that point, then '*len' is set to zero, and NULL is returned. - * The engine state is unmodified by this call. - * - * br_ssl_engine_xxx_ack - * Informs the engine that 'len' bytes have been read from the buffer - * (extract operation) or written to the buffer (inject operation). - * The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed - * that which was obtained from a preceding br_ssl_engine_xxx_buf() - * call. - */ - -/** - * \brief Get buffer for application data to send. - * - * If the engine is ready to accept application data to send to the - * peer, then this call returns a pointer to the buffer where such - * data shall be written, and its length is written in `*len`. - * Otherwise, `*len` is set to 0 and `NULL` is returned. - * - * \param cc SSL engine context. - * \param len receives the application data output buffer length, or 0. - * \return the application data output buffer, or `NULL`. - */ -unsigned char *br_ssl_engine_sendapp_buf( - const br_ssl_engine_context *cc, size_t *len); - -/** - * \brief Inform the engine of some new application data. - * - * After writing `len` bytes in the buffer returned by - * `br_ssl_engine_sendapp_buf()`, the application shall call this - * function to trigger any relevant processing. The `len` parameter - * MUST NOT be 0, and MUST NOT exceed the value obtained in the - * `br_ssl_engine_sendapp_buf()` call. - * - * \param cc SSL engine context. - * \param len number of bytes pushed (not zero). - */ -void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len); - -/** - * \brief Get buffer for received application data. - * - * If the engine has received application data from the peer, hen this - * call returns a pointer to the buffer from where such data shall be - * read, and its length is written in `*len`. Otherwise, `*len` is set - * to 0 and `NULL` is returned. - * - * \param cc SSL engine context. - * \param len receives the application data input buffer length, or 0. - * \return the application data input buffer, or `NULL`. - */ -unsigned char *br_ssl_engine_recvapp_buf( - const br_ssl_engine_context *cc, size_t *len); - -/** - * \brief Acknowledge some received application data. - * - * After reading `len` bytes from the buffer returned by - * `br_ssl_engine_recvapp_buf()`, the application shall call this - * function to trigger any relevant processing. The `len` parameter - * MUST NOT be 0, and MUST NOT exceed the value obtained in the - * `br_ssl_engine_recvapp_buf()` call. - * - * \param cc SSL engine context. - * \param len number of bytes read (not zero). - */ -void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len); - -/** - * \brief Get buffer for record data to send. - * - * If the engine has prepared some records to send to the peer, then this - * call returns a pointer to the buffer from where such data shall be - * read, and its length is written in `*len`. Otherwise, `*len` is set - * to 0 and `NULL` is returned. - * - * \param cc SSL engine context. - * \param len receives the record data output buffer length, or 0. - * \return the record data output buffer, or `NULL`. - */ -unsigned char *br_ssl_engine_sendrec_buf( - const br_ssl_engine_context *cc, size_t *len); - -/** - * \brief Acknowledge some sent record data. - * - * After reading `len` bytes from the buffer returned by - * `br_ssl_engine_sendrec_buf()`, the application shall call this - * function to trigger any relevant processing. The `len` parameter - * MUST NOT be 0, and MUST NOT exceed the value obtained in the - * `br_ssl_engine_sendrec_buf()` call. - * - * \param cc SSL engine context. - * \param len number of bytes read (not zero). - */ -void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len); - -/** - * \brief Get buffer for incoming records. - * - * If the engine is ready to accept records from the peer, then this - * call returns a pointer to the buffer where such data shall be - * written, and its length is written in `*len`. Otherwise, `*len` is - * set to 0 and `NULL` is returned. - * - * \param cc SSL engine context. - * \param len receives the record data input buffer length, or 0. - * \return the record data input buffer, or `NULL`. - */ -unsigned char *br_ssl_engine_recvrec_buf( - const br_ssl_engine_context *cc, size_t *len); - -/** - * \brief Inform the engine of some new record data. - * - * After writing `len` bytes in the buffer returned by - * `br_ssl_engine_recvrec_buf()`, the application shall call this - * function to trigger any relevant processing. The `len` parameter - * MUST NOT be 0, and MUST NOT exceed the value obtained in the - * `br_ssl_engine_recvrec_buf()` call. - * - * \param cc SSL engine context. - * \param len number of bytes pushed (not zero). - */ -void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len); - -/** - * \brief Flush buffered application data. - * - * If some application data has been buffered in the engine, then wrap - * it into a record and mark it for sending. If no application data has - * been buffered but the engine would be ready to accept some, AND the - * `force` parameter is non-zero, then an empty record is assembled and - * marked for sending. In all other cases, this function does nothing. - * - * Empty records are technically legal, but not all existing SSL/TLS - * implementations support them. Empty records can be useful as a - * transparent "keep-alive" mechanism to maintain some low-level - * network activity. - * - * \param cc SSL engine context. - * \param force non-zero to force sending an empty record. - */ -void br_ssl_engine_flush(br_ssl_engine_context *cc, int force); - -/** - * \brief Initiate a closure. - * - * If, at that point, the context is open and in ready state, then a - * `close_notify` alert is assembled and marked for sending; this - * triggers the closure protocol. Otherwise, no such alert is assembled. - * - * \param cc SSL engine context. - */ -void br_ssl_engine_close(br_ssl_engine_context *cc); - -/** - * \brief Initiate a renegotiation. - * - * If the engine is failed or closed, or if the peer is known not to - * support secure renegotiation (RFC 5746), or if renegotiations have - * been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there - * is buffered incoming application data, then this function returns 0 - * and nothing else happens. - * - * Otherwise, this function returns 1, and a renegotiation attempt is - * triggered (if a handshake is already ongoing at that point, then - * no new handshake is triggered). - * - * \param cc SSL engine context. - * \return 1 on success, 0 on error. - */ -int br_ssl_engine_renegotiate(br_ssl_engine_context *cc); - -/** - * \brief Export key material from a connected SSL engine (RFC 5705). - * - * This calls compute a secret key of arbitrary length from the master - * secret of a connected SSL engine. If the provided context is not - * currently in "application data" state (initial handshake is not - * finished, another handshake is ongoing, or the connection failed or - * was closed), then this function returns 0. Otherwise, a secret key of - * length `len` bytes is computed and written in the buffer pointed to - * by `dst`, and 1 is returned. - * - * The computed key follows the specification described in RFC 5705. - * That RFC includes two key computations, with and without a "context - * value". If `context` is `NULL`, then the variant without context is - * used; otherwise, the `context_len` bytes located at the address - * pointed to by `context` are used in the computation. Note that it - * is possible to have a "with context" key with a context length of - * zero bytes, by setting `context` to a non-`NULL` value but - * `context_len` to 0. - * - * When context bytes are used, the context length MUST NOT exceed - * 65535 bytes. - * - * \param cc SSL engine context. - * \param dst destination buffer for exported key. - * \param len exported key length (in bytes). - * \param label disambiguation label. - * \param context context value (or `NULL`). - * \param context_len context length (in bytes). - * \return 1 on success, 0 on error. - */ -int br_ssl_key_export(br_ssl_engine_context *cc, - void *dst, size_t len, const char *label, - const void *context, size_t context_len); - -/* - * Pre-declaration for the SSL client context. - */ -typedef struct br_ssl_client_context_ br_ssl_client_context; - -/** - * \brief Type for the client certificate, if requested by the server. - */ -typedef struct { - /** - * \brief Authentication type. - * - * This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA` - * (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange). - */ - int auth_type; - - /** - * \brief Hash function for computing the CertificateVerify. - * - * This is the symbolic identifier for the hash function that - * will be used to produce the hash of handshake messages, to - * be signed into the CertificateVerify. For full static ECDH - * (client and server certificates are both EC in the same - * curve, and static ECDH is used), this value is set to -1. - * - * Take care that with TLS 1.0 and 1.1, that value MUST match - * the protocol requirements: value must be 0 (MD5+SHA-1) for - * a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only - * TLS 1.2 allows for other hash functions. - */ - int hash_id; - - /** - * \brief Certificate chain to send to the server. - * - * This is an array of `br_x509_certificate` objects, each - * normally containing a DER-encoded certificate. The client - * code does not try to decode these elements. If there is no - * chain to send to the server, then this pointer shall be - * set to `NULL`. - */ - const br_x509_certificate *chain; - - /** - * \brief Certificate chain length (number of certificates). - * - * If there is no chain to send to the server, then this value - * shall be set to 0. - */ - size_t chain_len; - -} br_ssl_client_certificate; - -/* - * Note: the constants below for signatures match the TLS constants. - */ - -/** \brief Client authentication type: static ECDH. */ -#define BR_AUTH_ECDH 0 -/** \brief Client authentication type: RSA signature. */ -#define BR_AUTH_RSA 1 -/** \brief Client authentication type: ECDSA signature. */ -#define BR_AUTH_ECDSA 3 - -/** - * \brief Class type for a certificate handler (client side). - * - * A certificate handler selects a client certificate chain to send to - * the server, upon explicit request from that server. It receives - * the list of trust anchor DN from the server, and supported types - * of certificates and signatures, and returns the chain to use. It - * is also invoked to perform the corresponding private key operation - * (a signature, or an ECDH computation). - * - * The SSL client engine will first push the trust anchor DN with - * `start_name_list()`, `start_name()`, `append_name()`, `end_name()` - * and `end_name_list()`. Then it will call `choose()`, to select the - * actual chain (and signature/hash algorithms). Finally, it will call - * either `do_sign()` or `do_keyx()`, depending on the algorithm choices. - */ -typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class; -struct br_ssl_client_certificate_class_ { - /** - * \brief Context size (in bytes). - */ - size_t context_size; - - /** - * \brief Begin reception of a list of trust anchor names. This - * is called while parsing the incoming CertificateRequest. - * - * \param pctx certificate handler context. - */ - void (*start_name_list)(const br_ssl_client_certificate_class **pctx); - - /** - * \brief Begin reception of a new trust anchor name. - * - * The total encoded name length is provided; it is less than - * 65535 bytes. - * - * \param pctx certificate handler context. - * \param len encoded name length (in bytes). - */ - void (*start_name)(const br_ssl_client_certificate_class **pctx, - size_t len); - - /** - * \brief Receive some more bytes for the current trust anchor name. - * - * The provided reference (`data`) points to a transient buffer - * they may be reused as soon as this function returns. The chunk - * length (`len`) is never zero. - * - * \param pctx certificate handler context. - * \param data anchor name chunk. - * \param len anchor name chunk length (in bytes). - */ - void (*append_name)(const br_ssl_client_certificate_class **pctx, - const unsigned char *data, size_t len); - - /** - * \brief End current trust anchor name. - * - * This function is called when all the encoded anchor name data - * has been provided. - * - * \param pctx certificate handler context. - */ - void (*end_name)(const br_ssl_client_certificate_class **pctx); - - /** - * \brief End list of trust anchor names. - * - * This function is called when all the anchor names in the - * CertificateRequest message have been obtained. - * - * \param pctx certificate handler context. - */ - void (*end_name_list)(const br_ssl_client_certificate_class **pctx); - - /** - * \brief Select client certificate and algorithms. - * - * This callback function shall fill the provided `choices` - * structure with the selected algorithms and certificate chain. - * The `hash_id`, `chain` and `chain_len` fields must be set. If - * the client cannot or does not wish to send a certificate, - * then it shall set `chain` to `NULL` and `chain_len` to 0. - * - * The `auth_types` parameter describes the authentication types, - * signature algorithms and hash functions that are supported by - * both the client context and the server, and compatible with - * the current protocol version. This is a bit field with the - * following contents: - * - * - If RSA signatures with hash function x are supported, then - * bit x is set. - * - * - If ECDSA signatures with hash function x are supported, - * then bit 8+x is set. - * - * - If static ECDH is supported, with a RSA-signed certificate, - * then bit 16 is set. - * - * - If static ECDH is supported, with an ECDSA-signed certificate, - * then bit 17 is set. - * - * Notes: - * - * - When using TLS 1.0 or 1.1, the hash function for RSA - * signatures is always the special MD5+SHA-1 (id 0), and the - * hash function for ECDSA signatures is always SHA-1 (id 2). - * - * - When using TLS 1.2, the list of hash functions is trimmed - * down to include only hash functions that the client context - * can support. The actual server list can be obtained with - * `br_ssl_client_get_server_hashes()`; that list may be used - * to select the certificate chain to send to the server. - * - * \param pctx certificate handler context. - * \param cc SSL client context. - * \param auth_types supported authentication types and algorithms. - * \param choices destination structure for the policy choices. - */ - void (*choose)(const br_ssl_client_certificate_class **pctx, - const br_ssl_client_context *cc, uint32_t auth_types, - br_ssl_client_certificate *choices); - - /** - * \brief Perform key exchange (client part). - * - * This callback is invoked in case of a full static ECDH key - * exchange: - * - * - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`; - * - * - the server requests a client certificate; - * - * - the client has, and sends, a client certificate that - * uses an EC key in the same curve as the server's key, - * and chooses static ECDH (the `hash_id` field in the choice - * structure was set to -1). - * - * In that situation, this callback is invoked to compute the - * client-side ECDH: the provided `data` (of length `*len` bytes) - * is the server's public key point (as decoded from its - * certificate), and the client shall multiply that point with - * its own private key, and write back the X coordinate of the - * resulting point in the same buffer, starting at offset 0. - * The `*len` value shall be modified to designate the actual - * length of the X coordinate. - * - * The callback must uphold the following: - * - * - If the input array does not have the proper length for - * an encoded curve point, then an error (0) shall be reported. - * - * - If the input array has the proper length, then processing - * MUST be constant-time, even if the data is not a valid - * encoded point. - * - * - This callback MUST check that the input point is valid. - * - * Returned value is 1 on success, 0 on error. - * - * \param pctx certificate handler context. - * \param data server public key point. - * \param len public key point length / X coordinate length. - * \return 1 on success, 0 on error. - */ - uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx, - unsigned char *data, size_t *len); - - /** - * \brief Perform a signature (client authentication). - * - * This callback is invoked when a client certificate was sent, - * and static ECDH is not used. It shall compute a signature, - * using the client's private key, over the provided hash value - * (which is the hash of all previous handshake messages). - * - * On input, the hash value to sign is in `data`, of size - * `hv_len`; the involved hash function is identified by - * `hash_id`. The signature shall be computed and written - * back into `data`; the total size of that buffer is `len` - * bytes. - * - * This callback shall verify that the signature length does not - * exceed `len` bytes, and abstain from writing the signature if - * it does not fit. - * - * For RSA signatures, the `hash_id` may be 0, in which case - * this is the special header-less signature specified in TLS 1.0 - * and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1 - * v1.5 signatures shall be computed. - * - * For ECDSA signatures, the signature value shall use the ASN.1 - * based encoding. - * - * Returned value is the signature length (in bytes), or 0 on error. - * - * \param pctx certificate handler context. - * \param hash_id hash function identifier. - * \param hv_len hash value length (in bytes). - * \param data input/output buffer (hash value, then signature). - * \param len total buffer length (in bytes). - * \return signature length (in bytes) on success, or 0 on error. - */ - size_t (*do_sign)(const br_ssl_client_certificate_class **pctx, - int hash_id, size_t hv_len, unsigned char *data, size_t len); -}; - -/** - * \brief A single-chain RSA client certificate handler. - * - * This handler uses a single certificate chain, with a RSA - * signature. The list of trust anchor DN is ignored. - * - * Apart from the first field (vtable pointer), its contents are - * opaque and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_ssl_client_certificate_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - const br_x509_certificate *chain; - size_t chain_len; - const br_rsa_private_key *sk; - br_rsa_pkcs1_sign irsasign; -#endif -} br_ssl_client_certificate_rsa_context; - -/** - * \brief A single-chain EC client certificate handler. - * - * This handler uses a single certificate chain, with a RSA - * signature. The list of trust anchor DN is ignored. - * - * This handler may support both static ECDH, and ECDSA signatures - * (either usage may be selectively disabled). - * - * Apart from the first field (vtable pointer), its contents are - * opaque and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_ssl_client_certificate_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - const br_x509_certificate *chain; - size_t chain_len; - const br_ec_private_key *sk; - unsigned allowed_usages; - unsigned issuer_key_type; - const br_multihash_context *mhash; - const br_ec_impl *iec; - br_ecdsa_sign iecdsa; -#endif -} br_ssl_client_certificate_ec_context; - -/** - * \brief Context structure for a SSL client. - * - * The first field (called `eng`) is the SSL engine; all functions that - * work on a `br_ssl_engine_context` structure shall take as parameter - * a pointer to that field. The other structure fields are opaque and - * must not be accessed directly. - */ -struct br_ssl_client_context_ { - /** - * \brief The encapsulated engine context. - */ - br_ssl_engine_context eng; - -#ifndef BR_DOXYGEN_IGNORE - /* - * Minimum ClientHello length; padding with an extension (RFC - * 7685) is added if necessary to match at least that length. - * Such padding is nominally unnecessary, but it has been used - * to work around some server implementation bugs. - */ - uint16_t min_clienthello_len; - - /* - * Bit field for algorithms (hash + signature) supported by the - * server when requesting a client certificate. - */ - uint32_t hashes; - - /* - * Server's public key curve. - */ - int server_curve; - - /* - * Context for certificate handler. - */ - const br_ssl_client_certificate_class **client_auth_vtable; - - /* - * Client authentication type. - */ - unsigned char auth_type; - - /* - * Hash function to use for the client signature. This is 0xFF - * if static ECDH is used. - */ - unsigned char hash_id; - - /* - * For the core certificate handlers, thus avoiding (in most - * cases) the need for an externally provided policy context. - */ - union { - const br_ssl_client_certificate_class *vtable; - br_ssl_client_certificate_rsa_context single_rsa; - br_ssl_client_certificate_ec_context single_ec; - } client_auth; - - /* - * Implementations. - */ - br_rsa_public irsapub; -#endif -}; - -/** - * \brief Get the hash functions and signature algorithms supported by - * the server. - * - * This value is a bit field: - * - * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, - * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, - * or 2 to 6 for the SHA family). - * - * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` - * is set. - * - * - Newer algorithms are symbolic 16-bit identifiers that do not - * represent signature algorithm and hash function separately. If - * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 - * range, then bit `16+x` is set. - * - * "New algorithms" are currently defined only in draft documents, so - * this support is subject to possible change. Right now (early 2017), - * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA - * on Curve448) to bit 24. If the identifiers on the wire change in - * future document, then the decoding mechanism in BearSSL will be - * amended to keep mapping ed25519 and ed448 on bits 23 and 24, - * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not - * guaranteed yet. - * - * \param cc client context. - * \return the server-supported hash functions and signature algorithms. - */ -static inline uint32_t -br_ssl_client_get_server_hashes(const br_ssl_client_context *cc) -{ - return cc->hashes; -} - -/** - * \brief Get the server key curve. - * - * This function returns the ID for the curve used by the server's public - * key. This is set when the server's certificate chain is processed; - * this value is 0 if the server's key is not an EC key. - * - * \return the server's public key curve ID, or 0. - */ -static inline int -br_ssl_client_get_server_curve(const br_ssl_client_context *cc) -{ - return cc->server_curve; -} - -/* - * Each br_ssl_client_init_xxx() function sets the list of supported - * cipher suites and used implementations, as specified by the profile - * name 'xxx'. Defined profile names are: - * - * full all supported versions and suites; constant-time implementations - * TODO: add other profiles - */ - -/** - * \brief SSL client profile: full. - * - * This function initialises the provided SSL client context with - * all supported algorithms and cipher suites. It also initialises - * a companion X.509 validation engine with all supported algorithms, - * and the provided trust anchors; the X.509 engine will be used by - * the client context to validate the server's certificate. - * - * \param cc client context to initialise. - * \param xc X.509 validation context to initialise. - * \param trust_anchors trust anchors to use. - * \param trust_anchors_num number of trust anchors. - */ -void br_ssl_client_init_full(br_ssl_client_context *cc, - br_x509_minimal_context *xc, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); - -/** - * \brief Clear the complete contents of a SSL client context. - * - * Everything is cleared, including the reference to the configured buffer, - * implementations, cipher suites and state. This is a preparatory step - * to assembling a custom profile. - * - * \param cc client context to clear. - */ -void br_ssl_client_zero(br_ssl_client_context *cc); - -/** - * \brief Set an externally provided client certificate handler context. - * - * The handler's methods are invoked when the server requests a client - * certificate. - * - * \param cc client context. - * \param pctx certificate handler context (pointer to its vtable field). - */ -static inline void -br_ssl_client_set_client_certificate(br_ssl_client_context *cc, - const br_ssl_client_certificate_class **pctx) -{ - cc->client_auth_vtable = pctx; -} - -/** - * \brief Set the RSA public-key operations implementation. - * - * This will be used to encrypt the pre-master secret with the server's - * RSA public key (RSA-encryption cipher suites only). - * - * \param cc client context. - * \param irsapub RSA public-key encryption implementation. - */ -static inline void -br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub) -{ - cc->irsapub = irsapub; -} - -/** - * \brief Set the "default" RSA implementation for public-key operations. - * - * This sets the RSA implementation in the client context (for encrypting - * the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest - * available on the current platform. - * - * \param cc client context. - */ -void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc); - -/** - * \brief Set the minimum ClientHello length (RFC 7685 padding). - * - * If this value is set and the ClientHello would be shorter, then - * the Pad ClientHello extension will be added with enough padding bytes - * to reach the target size. Because of the extension header, the resulting - * size will sometimes be slightly more than `len` bytes if the target - * size cannot be exactly met. - * - * The target length relates to the _contents_ of the ClientHello, not - * counting its 4-byte header. For instance, if `len` is set to 512, - * then the padding will bring the ClientHello size to 516 bytes with its - * header, and 521 bytes when counting the 5-byte record header. - * - * \param cc client context. - * \param len minimum ClientHello length (in bytes). - */ -static inline void -br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len) -{ - cc->min_clienthello_len = len; -} - -/** - * \brief Prepare or reset a client context for a new connection. - * - * The `server_name` parameter is used to fill the SNI extension; the - * X.509 "minimal" engine will also match that name against the server - * names included in the server's certificate. If the parameter is - * `NULL` then no SNI extension will be sent, and the X.509 "minimal" - * engine (if used for server certificate validation) will not check - * presence of any specific name in the received certificate. - * - * Therefore, setting the `server_name` to `NULL` shall be reserved - * to cases where alternate or additional methods are used to ascertain - * that the right server public key is used (e.g. a "known key" model). - * - * If `resume_session` is non-zero and the context was previously used - * then the session parameters may be reused (depending on whether the - * server previously sent a non-empty session ID, and accepts the session - * resumption). The session parameters for session resumption can also - * be set explicitly with `br_ssl_engine_set_session_parameters()`. - * - * On failure, the context is marked as failed, and this function - * returns 0. A possible failure condition is when no initial entropy - * was injected, and none could be obtained from the OS (either OS - * randomness gathering is not supported, or it failed). - * - * \param cc client context. - * \param server_name target server name, or `NULL`. - * \param resume_session non-zero to try session resumption. - * \return 0 on failure, 1 on success. - */ -int br_ssl_client_reset(br_ssl_client_context *cc, - const char *server_name, int resume_session); - -/** - * \brief Forget any session in the context. - * - * This means that the next handshake that uses this context will - * necessarily be a full handshake (this applies both to new connections - * and to renegotiations). - * - * \param cc client context. - */ -static inline void -br_ssl_client_forget_session(br_ssl_client_context *cc) -{ - cc->eng.session.session_id_len = 0; -} - -/** - * \brief Set client certificate chain and key (single RSA case). - * - * This function sets a client certificate chain, that the client will - * send to the server whenever a client certificate is requested. This - * certificate uses an RSA public key; the corresponding private key is - * invoked for authentication. Trust anchor names sent by the server are - * ignored. - * - * The provided chain and private key are linked in the client context; - * they must remain valid as long as they may be used, i.e. normally - * for the duration of the connection, since they might be invoked - * again upon renegotiations. - * - * \param cc SSL client context. - * \param chain client certificate chain (SSL order: EE comes first). - * \param chain_len client chain length (number of certificates). - * \param sk client private key. - * \param irsasign RSA signature implementation (PKCS#1 v1.5). - */ -void br_ssl_client_set_single_rsa(br_ssl_client_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign); - -/* - * \brief Set the client certificate chain and key (single EC case). - * - * This function sets a client certificate chain, that the client will - * send to the server whenever a client certificate is requested. This - * certificate uses an EC public key; the corresponding private key is - * invoked for authentication. Trust anchor names sent by the server are - * ignored. - * - * The provided chain and private key are linked in the client context; - * they must remain valid as long as they may be used, i.e. normally - * for the duration of the connection, since they might be invoked - * again upon renegotiations. - * - * The `allowed_usages` is a combination of usages, namely - * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX` - * value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value - * allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA - * signature implementation must be provided; otherwise, the `iecdsa` - * parameter may be 0. - * - * The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or - * `BR_KEYTYPE_EC`; it is the type of the public key used the the CA - * that issued (signed) the client certificate. That value is used with - * full static ECDH: support of the certificate by the server depends - * on how the certificate was signed. (Note: when using TLS 1.2, this - * parameter is ignored; but its value matters for TLS 1.0 and 1.1.) - * - * \param cc server context. - * \param chain server certificate chain to send. - * \param chain_len chain length (number of certificates). - * \param sk server private key (EC). - * \param allowed_usages allowed private key usages. - * \param cert_issuer_key_type issuing CA's key type. - * \param iec EC core implementation. - * \param iecdsa ECDSA signature implementation ("asn1" format). - */ -void br_ssl_client_set_single_ec(br_ssl_client_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk, unsigned allowed_usages, - unsigned cert_issuer_key_type, - const br_ec_impl *iec, br_ecdsa_sign iecdsa); - -/** - * \brief Type for a "translated cipher suite", as an array of two - * 16-bit integers. - * - * The first element is the cipher suite identifier (as used on the wire). - * The second element is the concatenation of four 4-bit elements which - * characterise the cipher suite contents. In most to least significant - * order, these 4-bit elements are: - * - * - Bits 12 to 15: key exchange + server key type - * - * | val | symbolic constant | suite type | details | - * | :-- | :----------------------- | :---------- | :----------------------------------------------- | - * | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) | - * | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) | - * | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) | - * | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA | - * | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA | - * - * - Bits 8 to 11: symmetric encryption algorithm - * - * | val | symbolic constant | symmetric encryption | key strength (bits) | - * | :-- | :--------------------- | :------------------- | :------------------ | - * | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 | - * | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 | - * | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 | - * | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 | - * | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 | - * | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 | - * - * - Bits 4 to 7: MAC algorithm - * - * | val | symbolic constant | MAC type | details | - * | :-- | :----------------- | :----------- | :------------------------------------ | - * | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) | - * | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` | - * | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` | - * | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` | - * - * - Bits 0 to 3: hash function for PRF when used with TLS-1.2 - * - * | val | symbolic constant | hash function | details | - * | :-- | :----------------- | :------------ | :----------------------------------- | - * | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` | - * | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` | - * - * For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has - * standard identifier 0x009C, and is translated to 0x0304, for, in - * that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0), - * SHA-256 in the TLS PRF (4). - */ -typedef uint16_t br_suite_translated[2]; - -#ifndef BR_DOXYGEN_IGNORE -/* - * Constants are already documented in the br_suite_translated type. - */ - -#define BR_SSLKEYX_RSA 0 -#define BR_SSLKEYX_ECDHE_RSA 1 -#define BR_SSLKEYX_ECDHE_ECDSA 2 -#define BR_SSLKEYX_ECDH_RSA 3 -#define BR_SSLKEYX_ECDH_ECDSA 4 - -#define BR_SSLENC_3DES_CBC 0 -#define BR_SSLENC_AES128_CBC 1 -#define BR_SSLENC_AES256_CBC 2 -#define BR_SSLENC_AES128_GCM 3 -#define BR_SSLENC_AES256_GCM 4 -#define BR_SSLENC_CHACHA20 5 - -#define BR_SSLMAC_AEAD 0 -#define BR_SSLMAC_SHA1 br_sha1_ID -#define BR_SSLMAC_SHA256 br_sha256_ID -#define BR_SSLMAC_SHA384 br_sha384_ID - -#define BR_SSLPRF_SHA256 br_sha256_ID -#define BR_SSLPRF_SHA384 br_sha384_ID - -#endif - -/* - * Pre-declaration for the SSL server context. - */ -typedef struct br_ssl_server_context_ br_ssl_server_context; - -/** - * \brief Type for the server policy choices, taken after analysis of - * the client message (ClientHello). - */ -typedef struct { - /** - * \brief Cipher suite to use with that client. - */ - uint16_t cipher_suite; - - /** - * \brief Hash function or algorithm for signing the ServerKeyExchange. - * - * This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*` - * cipher suites; it is used only for `TLS_ECDHE_*` suites, in - * which the server _signs_ the ephemeral EC Diffie-Hellman - * parameters sent to the client. - * - * This identifier must be one of the following values: - * - * - `0xFF00 + id`, where `id` is a hash function identifier - * (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions); - * - * - a full 16-bit identifier, lower than `0xFF00`. - * - * If the first option is used, then the SSL engine will - * compute the hash of the data that is to be signed, with the - * designated hash function. The `do_sign()` method will be - * invoked with that hash value provided in the the `data` - * buffer. - * - * If the second option is used, then the SSL engine will NOT - * compute a hash on the data; instead, it will provide the - * to-be-signed data itself in `data`, i.e. the concatenation of - * the client random, server random, and encoded ECDH - * parameters. Furthermore, with TLS-1.2 and later, the 16-bit - * identifier will be used "as is" in the protocol, in the - * SignatureAndHashAlgorithm; for instance, `0x0401` stands for - * RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash - * function (the `04`). - * - * Take care that with TLS 1.0 and 1.1, the hash function is - * constrainted by the protocol: RSA signature must use - * MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1 - * (`0xFF02`). Since TLS 1.0 and 1.1 don't include a - * SignatureAndHashAlgorithm field in their ServerKeyExchange - * messages, any value below `0xFF00` will be usable to send the - * raw ServerKeyExchange data to the `do_sign()` callback, but - * that callback must still follow the protocol requirements - * when generating the signature. - */ - unsigned algo_id; - - /** - * \brief Certificate chain to send to the client. - * - * This is an array of `br_x509_certificate` objects, each - * normally containing a DER-encoded certificate. The server - * code does not try to decode these elements. - */ - const br_x509_certificate *chain; - - /** - * \brief Certificate chain length (number of certificates). - */ - size_t chain_len; - -} br_ssl_server_choices; - -/** - * \brief Class type for a policy handler (server side). - * - * A policy handler selects the policy parameters for a connection - * (cipher suite and other algorithms, and certificate chain to send to - * the client); it also performs the server-side computations involving - * its permanent private key. - * - * The SSL server engine will invoke first `choose()`, once the - * ClientHello message has been received, then either `do_keyx()` - * `do_sign()`, depending on the cipher suite. - */ -typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class; -struct br_ssl_server_policy_class_ { - /** - * \brief Context size (in bytes). - */ - size_t context_size; - - /** - * \brief Select algorithms and certificates for this connection. - * - * This callback function shall fill the provided `choices` - * structure with the policy choices for this connection. This - * entails selecting the cipher suite, hash function for signing - * the ServerKeyExchange (applicable only to ECDHE cipher suites), - * and certificate chain to send. - * - * The callback receives a pointer to the server context that - * contains the relevant data. In particular, the functions - * `br_ssl_server_get_client_suites()`, - * `br_ssl_server_get_client_hashes()` and - * `br_ssl_server_get_client_curves()` can be used to obtain - * the cipher suites, hash functions and elliptic curves - * supported by both the client and server, respectively. The - * `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()` - * functions yield the protocol version and requested server name - * (SNI), respectively. - * - * This function may modify its context structure (`pctx`) in - * arbitrary ways to keep track of its own choices. - * - * This function shall return 1 if appropriate policy choices - * could be made, or 0 if this connection cannot be pursued. - * - * \param pctx policy context. - * \param cc SSL server context. - * \param choices destination structure for the policy choices. - * \return 1 on success, 0 on error. - */ - int (*choose)(const br_ssl_server_policy_class **pctx, - const br_ssl_server_context *cc, - br_ssl_server_choices *choices); - - /** - * \brief Perform key exchange (server part). - * - * This callback is invoked to perform the server-side cryptographic - * operation for a key exchange that is not ECDHE. This callback - * uses the private key. - * - * **For RSA key exchange**, the provided `data` (of length `*len` - * bytes) shall be decrypted with the server's private key, and - * the 48-byte premaster secret copied back to the first 48 bytes - * of `data`. - * - * - The caller makes sure that `*len` is at least 59 bytes. - * - * - This callback MUST check that the provided length matches - * that of the key modulus; it shall report an error otherwise. - * - * - If the length matches that of the RSA key modulus, then - * processing MUST be constant-time, even if decryption fails, - * or the padding is incorrect, or the plaintext message length - * is not exactly 48 bytes. - * - * - This callback needs not check the two first bytes of the - * obtained pre-master secret (the caller will do that). - * - * - If an error is reported (0), then what the callback put - * in the first 48 bytes of `data` is unimportant (the caller - * will use random bytes instead). - * - * **For ECDH key exchange**, the provided `data` (of length `*len` - * bytes) is the elliptic curve point from the client. The - * callback shall multiply it with its private key, and store - * the resulting X coordinate in `data`, starting at offset 0, - * and set `*len` to the length of the X coordinate. - * - * - If the input array does not have the proper length for - * an encoded curve point, then an error (0) shall be reported. - * - * - If the input array has the proper length, then processing - * MUST be constant-time, even if the data is not a valid - * encoded point. - * - * - This callback MUST check that the input point is valid. - * - * Returned value is 1 on success, 0 on error. - * - * \param pctx policy context. - * \param data key exchange data from the client. - * \param len key exchange data length (in bytes). - * \return 1 on success, 0 on error. - */ - uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx, - unsigned char *data, size_t *len); - - /** - * \brief Perform a signature (for a ServerKeyExchange message). - * - * This callback function is invoked for ECDHE cipher suites. On - * input, the hash value or message to sign is in `data`, of - * size `hv_len`; the involved hash function or algorithm is - * identified by `algo_id`. The signature shall be computed and - * written back into `data`; the total size of that buffer is - * `len` bytes. - * - * This callback shall verify that the signature length does not - * exceed `len` bytes, and abstain from writing the signature if - * it does not fit. - * - * The `algo_id` value matches that which was written in the - * `choices` structures by the `choose()` callback. This will be - * one of the following: - * - * - `0xFF00 + id` for a hash function identifier `id`. In - * that case, the `data` buffer contains a hash value - * already computed over the data that is to be signed, - * of length `hv_len`. The `id` may be 0 to designate the - * special MD5+SHA-1 concatenation (old-style RSA signing). - * - * - Another value, lower than `0xFF00`. The `data` buffer - * then contains the raw, non-hashed data to be signed - * (concatenation of the client and server randoms and - * ECDH parameters). The callback is responsible to apply - * any relevant hashing as part of the signing process. - * - * Returned value is the signature length (in bytes), or 0 on error. - * - * \param pctx policy context. - * \param algo_id hash function / algorithm identifier. - * \param data input/output buffer (message/hash, then signature). - * \param hv_len hash value or message length (in bytes). - * \param len total buffer length (in bytes). - * \return signature length (in bytes) on success, or 0 on error. - */ - size_t (*do_sign)(const br_ssl_server_policy_class **pctx, - unsigned algo_id, - unsigned char *data, size_t hv_len, size_t len); -}; - -/** - * \brief A single-chain RSA policy handler. - * - * This policy context uses a single certificate chain, and a RSA - * private key. The context can be restricted to only signatures or - * only key exchange. - * - * Apart from the first field (vtable pointer), its contents are - * opaque and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_ssl_server_policy_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - const br_x509_certificate *chain; - size_t chain_len; - const br_rsa_private_key *sk; - unsigned allowed_usages; - br_rsa_private irsacore; - br_rsa_pkcs1_sign irsasign; -#endif -} br_ssl_server_policy_rsa_context; - -/** - * \brief A single-chain EC policy handler. - * - * This policy context uses a single certificate chain, and an EC - * private key. The context can be restricted to only signatures or - * only key exchange. - * - * Due to how TLS is defined, this context must be made aware whether - * the server certificate was itself signed with RSA or ECDSA. The code - * does not try to decode the certificate to obtain that information. - * - * Apart from the first field (vtable pointer), its contents are - * opaque and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_ssl_server_policy_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - const br_x509_certificate *chain; - size_t chain_len; - const br_ec_private_key *sk; - unsigned allowed_usages; - unsigned cert_issuer_key_type; - const br_multihash_context *mhash; - const br_ec_impl *iec; - br_ecdsa_sign iecdsa; -#endif -} br_ssl_server_policy_ec_context; - -/** - * \brief Class type for a session parameter cache. - * - * Session parameters are saved in the cache with `save()`, and - * retrieved with `load()`. The cache implementation can apply any - * storage and eviction strategy that it sees fit. The SSL server - * context that performs the request is provided, so that its - * functionalities may be used by the implementation (e.g. hash - * functions or random number generation). - */ -typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class; -struct br_ssl_session_cache_class_ { - /** - * \brief Context size (in bytes). - */ - size_t context_size; - - /** - * \brief Record a session. - * - * This callback should record the provided session parameters. - * The `params` structure is transient, so its contents shall - * be copied into the cache. The session ID has been randomly - * generated and always has length exactly 32 bytes. - * - * \param ctx session cache context. - * \param server_ctx SSL server context. - * \param params session parameters to save. - */ - void (*save)(const br_ssl_session_cache_class **ctx, - br_ssl_server_context *server_ctx, - const br_ssl_session_parameters *params); - - /** - * \brief Lookup a session in the cache. - * - * The session ID to lookup is in `params` and always has length - * exactly 32 bytes. If the session parameters are found in the - * cache, then the parameters shall be copied into the `params` - * structure. Returned value is 1 on successful lookup, 0 - * otherwise. - * - * \param ctx session cache context. - * \param server_ctx SSL server context. - * \param params destination for session parameters. - * \return 1 if found, 0 otherwise. - */ - int (*load)(const br_ssl_session_cache_class **ctx, - br_ssl_server_context *server_ctx, - br_ssl_session_parameters *params); -}; - -/** - * \brief Context for a basic cache system. - * - * The system stores session parameters in a buffer provided at - * initialisation time. Each entry uses exactly 100 bytes, and - * buffer sizes up to 4294967295 bytes are supported. - * - * Entries are evicted with a LRU (Least Recently Used) policy. A - * search tree is maintained to keep lookups fast even with large - * caches. - * - * Apart from the first field (vtable pointer), the structure - * contents are opaque and shall not be accessed directly. - */ -typedef struct { - /** \brief Pointer to vtable. */ - const br_ssl_session_cache_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - unsigned char *store; - size_t store_len, store_ptr; - unsigned char index_key[32]; - const br_hash_class *hash; - int init_done; - uint32_t head, tail, root; -#endif -} br_ssl_session_cache_lru; - -/** - * \brief Initialise a LRU session cache with the provided storage space. - * - * The provided storage space must remain valid as long as the cache - * is used. Arbitrary lengths are supported, up to 4294967295 bytes; - * each entry uses up exactly 100 bytes. - * - * \param cc session cache context. - * \param store storage space for cached entries. - * \param store_len storage space length (in bytes). - */ -void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, - unsigned char *store, size_t store_len); - -/** - * \brief Forget an entry in an LRU session cache. - * - * The session cache context must have been initialised. The entry - * with the provided session ID (of exactly 32 bytes) is looked for - * in the cache; if located, it is disabled. - * - * \param cc session cache context. - * \param id session ID to forget. - */ -void br_ssl_session_cache_lru_forget( - br_ssl_session_cache_lru *cc, const unsigned char *id); - -/** - * \brief Context structure for a SSL server. - * - * The first field (called `eng`) is the SSL engine; all functions that - * work on a `br_ssl_engine_context` structure shall take as parameter - * a pointer to that field. The other structure fields are opaque and - * must not be accessed directly. - */ -struct br_ssl_server_context_ { - /** - * \brief The encapsulated engine context. - */ - br_ssl_engine_context eng; - -#ifndef BR_DOXYGEN_IGNORE - /* - * Maximum version from the client. - */ - uint16_t client_max_version; - - /* - * Session cache. - */ - const br_ssl_session_cache_class **cache_vtable; - - /* - * Translated cipher suites supported by the client. The list - * is trimmed to include only the cipher suites that the - * server also supports; they are in the same order as in the - * client message. - */ - br_suite_translated client_suites[BR_MAX_CIPHER_SUITES]; - unsigned char client_suites_num; - - /* - * Hash functions supported by the client, with ECDSA and RSA - * (bit mask). For hash function with id 'x', set bit index is - * x for RSA, x+8 for ECDSA. For newer algorithms, with ID - * 0x08**, bit 16+k is set for algorithm 0x0800+k. - */ - uint32_t hashes; - - /* - * Curves supported by the client (bit mask, for named curves). - */ - uint32_t curves; - - /* - * Context for chain handler. - */ - const br_ssl_server_policy_class **policy_vtable; - uint16_t sign_hash_id; - - /* - * For the core handlers, thus avoiding (in most cases) the - * need for an externally provided policy context. - */ - union { - const br_ssl_server_policy_class *vtable; - br_ssl_server_policy_rsa_context single_rsa; - br_ssl_server_policy_ec_context single_ec; - } chain_handler; - - /* - * Buffer for the ECDHE private key. - */ - unsigned char ecdhe_key[70]; - size_t ecdhe_key_len; - - /* - * Trust anchor names for client authentication. "ta_names" and - * "tas" cannot be both non-NULL. - */ - const br_x500_name *ta_names; - const br_x509_trust_anchor *tas; - size_t num_tas; - size_t cur_dn_index; - const unsigned char *cur_dn; - size_t cur_dn_len; - - /* - * Buffer for the hash value computed over all handshake messages - * prior to CertificateVerify, and identifier for the hash function. - */ - unsigned char hash_CV[64]; - size_t hash_CV_len; - int hash_CV_id; - - /* - * Server-specific implementations. - * (none for now) - */ -#endif -}; - -/* - * Each br_ssl_server_init_xxx() function sets the list of supported - * cipher suites and used implementations, as specified by the profile - * name 'xxx'. Defined profile names are: - * - * full_rsa all supported algorithm, server key type is RSA - * full_ec all supported algorithm, server key type is EC - * TODO: add other profiles - * - * Naming scheme for "minimal" profiles: min123 - * - * -- character 1: key exchange - * r = RSA - * e = ECDHE_RSA - * f = ECDHE_ECDSA - * u = ECDH_RSA - * v = ECDH_ECDSA - * -- character 2: version / PRF - * 0 = TLS 1.0 / 1.1 with MD5+SHA-1 - * 2 = TLS 1.2 with SHA-256 - * 3 = TLS 1.2 with SHA-384 - * -- character 3: encryption - * a = AES/CBC - * d = 3DES/CBC - * g = AES/GCM - * c = ChaCha20+Poly1305 - */ - -/** - * \brief SSL server profile: full_rsa. - * - * This function initialises the provided SSL server context with - * all supported algorithms and cipher suites that rely on a RSA - * key pair. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk RSA private key. - */ -void br_ssl_server_init_full_rsa(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk); - -/** - * \brief SSL server profile: full_ec. - * - * This function initialises the provided SSL server context with - * all supported algorithms and cipher suites that rely on an EC - * key pair. - * - * The key type of the CA that issued the server's certificate must - * be provided, since it matters for ECDH cipher suites (ECDH_RSA - * suites require a RSA-powered CA). The key type is either - * `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len chain length (number of certificates). - * \param cert_issuer_key_type certificate issuer's key type. - * \param sk EC private key. - */ -void br_ssl_server_init_full_ec(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - unsigned cert_issuer_key_type, const br_ec_private_key *sk); - -/** - * \brief SSL server profile: minr2g. - * - * This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is - * RSA, and RSA key exchange is used (not forward secure, but uses little - * CPU in the client). - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk RSA private key. - */ -void br_ssl_server_init_minr2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk); - -/** - * \brief SSL server profile: mine2g. - * - * This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key - * is RSA, and ECDHE key exchange is used. This suite provides forward - * security, with a higher CPU expense on the client, and a somewhat - * larger code footprint (compared to "minr2g"). - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk RSA private key. - */ -void br_ssl_server_init_mine2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk); - -/** - * \brief SSL server profile: minf2g. - * - * This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256. - * Server key is EC, and ECDHE key exchange is used. This suite provides - * forward security, with a higher CPU expense on the client and server - * (by a factor of about 3 to 4), and a somewhat larger code footprint - * (compared to "minu2g" and "minv2g"). - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk EC private key. - */ -void br_ssl_server_init_minf2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk); - -/** - * \brief SSL server profile: minu2g. - * - * This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256. - * Server key is EC, and ECDH key exchange is used; the issuing CA used - * a RSA key. - * - * The "minu2g" and "minv2g" profiles do not provide forward secrecy, - * but are the lightest on the server (for CPU usage), and are rather - * inexpensive on the client as well. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk EC private key. - */ -void br_ssl_server_init_minu2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk); - -/** - * \brief SSL server profile: minv2g. - * - * This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256. - * Server key is EC, and ECDH key exchange is used; the issuing CA used - * an EC key. - * - * The "minu2g" and "minv2g" profiles do not provide forward secrecy, - * but are the lightest on the server (for CPU usage), and are rather - * inexpensive on the client as well. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk EC private key. - */ -void br_ssl_server_init_minv2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk); - -/** - * \brief SSL server profile: mine2c. - * - * This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. - * Server key is RSA, and ECDHE key exchange is used. This suite - * provides forward security. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk RSA private key. - */ -void br_ssl_server_init_mine2c(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk); - -/** - * \brief SSL server profile: minf2c. - * - * This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. - * Server key is EC, and ECDHE key exchange is used. This suite provides - * forward security. - * - * \param cc server context to initialise. - * \param chain server certificate chain. - * \param chain_len certificate chain length (number of certificate). - * \param sk EC private key. - */ -void br_ssl_server_init_minf2c(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk); - -/** - * \brief Get the supported client suites. - * - * This function shall be called only after the ClientHello has been - * processed, typically from the policy engine. The returned array - * contains the cipher suites that are supported by both the client - * and the server; these suites are in client preference order, unless - * the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case - * they are in server preference order. - * - * The suites are _translated_, which means that each suite is given - * as two 16-bit integers: the standard suite identifier, and its - * translated version, broken down into its individual components, - * as explained with the `br_suite_translated` type. - * - * The returned array is allocated in the context and will be rewritten - * by each handshake. - * - * \param cc server context. - * \param num receives the array size (number of suites). - * \return the translated common cipher suites, in preference order. - */ -static inline const br_suite_translated * -br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num) -{ - *num = cc->client_suites_num; - return cc->client_suites; -} - -/** - * \brief Get the hash functions and signature algorithms supported by - * the client. - * - * This value is a bit field: - * - * - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`, - * then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1, - * or 2 to 6 for the SHA family). - * - * - If ECDSA is supported with hash function of ID `x`, then bit `8+x` - * is set. - * - * - Newer algorithms are symbolic 16-bit identifiers that do not - * represent signature algorithm and hash function separately. If - * the TLS-level identifier is `0x0800+x` for a `x` in the 0..15 - * range, then bit `16+x` is set. - * - * "New algorithms" are currently defined only in draft documents, so - * this support is subject to possible change. Right now (early 2017), - * this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA - * on Curve448) to bit 24. If the identifiers on the wire change in - * future document, then the decoding mechanism in BearSSL will be - * amended to keep mapping ed25519 and ed448 on bits 23 and 24, - * respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not - * guaranteed yet. - * - * \param cc server context. - * \return the client-supported hash functions and signature algorithms. - */ -static inline uint32_t -br_ssl_server_get_client_hashes(const br_ssl_server_context *cc) -{ - return cc->hashes; -} - -/** - * \brief Get the elliptic curves supported by the client. - * - * This is a bit field (bit x is set if curve of ID x is supported). - * - * \param cc server context. - * \return the client-supported elliptic curves. - */ -static inline uint32_t -br_ssl_server_get_client_curves(const br_ssl_server_context *cc) -{ - return cc->curves; -} - -/** - * \brief Clear the complete contents of a SSL server context. - * - * Everything is cleared, including the reference to the configured buffer, - * implementations, cipher suites and state. This is a preparatory step - * to assembling a custom profile. - * - * \param cc server context to clear. - */ -void br_ssl_server_zero(br_ssl_server_context *cc); - -/** - * \brief Set an externally provided policy context. - * - * The policy context's methods are invoked to decide the cipher suite - * and certificate chain, and to perform operations involving the server's - * private key. - * - * \param cc server context. - * \param pctx policy context (pointer to its vtable field). - */ -static inline void -br_ssl_server_set_policy(br_ssl_server_context *cc, - const br_ssl_server_policy_class **pctx) -{ - cc->policy_vtable = pctx; -} - -/** - * \brief Set the server certificate chain and key (single RSA case). - * - * This function uses a policy context included in the server context. - * It configures use of a single server certificate chain with a RSA - * private key. The `allowed_usages` is a combination of usages, namely - * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables - * the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for - * key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures). - * - * \param cc server context. - * \param chain server certificate chain to send to the client. - * \param chain_len chain length (number of certificates). - * \param sk server private key (RSA). - * \param allowed_usages allowed private key usages. - * \param irsacore RSA core implementation. - * \param irsasign RSA signature implementation (PKCS#1 v1.5). - */ -void br_ssl_server_set_single_rsa(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk, unsigned allowed_usages, - br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign); - -/** - * \brief Set the server certificate chain and key (single EC case). - * - * This function uses a policy context included in the server context. - * It configures use of a single server certificate chain with an EC - * private key. The `allowed_usages` is a combination of usages, namely - * `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables - * the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for - * key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures). - * - * In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH), - * the algorithm type of the key used by the issuing CA to sign the - * server's certificate must be provided, as `cert_issuer_key_type` - * parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`). - * - * \param cc server context. - * \param chain server certificate chain to send. - * \param chain_len chain length (number of certificates). - * \param sk server private key (EC). - * \param allowed_usages allowed private key usages. - * \param cert_issuer_key_type issuing CA's key type. - * \param iec EC core implementation. - * \param iecdsa ECDSA signature implementation ("asn1" format). - */ -void br_ssl_server_set_single_ec(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk, unsigned allowed_usages, - unsigned cert_issuer_key_type, - const br_ec_impl *iec, br_ecdsa_sign iecdsa); - -/** - * \brief Activate client certificate authentication. - * - * The trust anchor encoded X.500 names (DN) to send to the client are - * provided. A client certificate will be requested and validated through - * the X.509 validator configured in the SSL engine. If `num` is 0, then - * client certificate authentication is disabled. - * - * If the client does not send a certificate, or on validation failure, - * the handshake aborts. Unauthenticated clients can be tolerated by - * setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag. - * - * The provided array is linked in, not copied, so that pointer must - * remain valid as long as anchor names may be used. - * - * \param cc server context. - * \param ta_names encoded trust anchor names. - * \param num number of encoded trust anchor names. - */ -static inline void -br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc, - const br_x500_name *ta_names, size_t num) -{ - cc->ta_names = ta_names; - cc->tas = NULL; - cc->num_tas = num; -} - -/** - * \brief Activate client certificate authentication. - * - * This is a variant for `br_ssl_server_set_trust_anchor_names()`: the - * trust anchor names are provided not as an array of stand-alone names - * (`br_x500_name` structures), but as an array of trust anchors - * (`br_x509_trust_anchor` structures). The server engine itself will - * only use the `dn` field of each trust anchor. This is meant to allow - * defining a single array of trust anchors, to be used here and in the - * X.509 validation engine itself. - * - * The provided array is linked in, not copied, so that pointer must - * remain valid as long as anchor names may be used. - * - * \param cc server context. - * \param tas trust anchors (only names are used). - * \param num number of trust anchors. - */ -static inline void -br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc, - const br_x509_trust_anchor *tas, size_t num) -{ - cc->ta_names = NULL; - cc->tas = tas; - cc->num_tas = num; -} - -/** - * \brief Configure the cache for session parameters. - * - * The cache context is provided as a pointer to its first field (vtable - * pointer). - * - * \param cc server context. - * \param vtable session cache context. - */ -static inline void -br_ssl_server_set_cache(br_ssl_server_context *cc, - const br_ssl_session_cache_class **vtable) -{ - cc->cache_vtable = vtable; -} - -/** - * \brief Prepare or reset a server context for handling an incoming client. - * - * \param cc server context. - * \return 1 on success, 0 on error. - */ -int br_ssl_server_reset(br_ssl_server_context *cc); - -/* ===================================================================== */ - -/* - * Context for the simplified I/O context. The transport medium is accessed - * through the low_read() and low_write() callback functions, each with - * its own opaque context pointer. - * - * low_read() read some bytes, at most 'len' bytes, into data[]. The - * returned value is the number of read bytes, or -1 on error. - * The 'len' parameter is guaranteed never to exceed 20000, - * so the length always fits in an 'int' on all platforms. - * - * low_write() write up to 'len' bytes, to be read from data[]. The - * returned value is the number of written bytes, or -1 on - * error. The 'len' parameter is guaranteed never to exceed - * 20000, so the length always fits in an 'int' on all - * parameters. - * - * A socket closure (if the transport medium is a socket) should be reported - * as an error (-1). The callbacks shall endeavour to block until at least - * one byte can be read or written; a callback returning 0 at times is - * acceptable, but this normally leads to the callback being immediately - * called again, so the callback should at least always try to block for - * some time if no I/O can take place. - * - * The SSL engine naturally applies some buffering, so the callbacks need - * not apply buffers of their own. - */ -/** - * \brief Context structure for the simplified SSL I/O wrapper. - * - * This structure is initialised with `br_sslio_init()`. Its contents - * are opaque and shall not be accessed directly. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - br_ssl_engine_context *engine; - int (*low_read)(void *read_context, - unsigned char *data, size_t len); - void *read_context; - int (*low_write)(void *write_context, - const unsigned char *data, size_t len); - void *write_context; -#endif -} br_sslio_context; - -/** - * \brief Initialise a simplified I/O wrapper context. - * - * The simplified I/O wrapper offers a simpler read/write API for a SSL - * engine (client or server), using the provided callback functions for - * reading data from, or writing data to, the transport medium. - * - * The callback functions have the following semantics: - * - * - Each callback receives an opaque context value (of type `void *`) - * that the callback may use arbitrarily (or possibly ignore). - * - * - `low_read()` reads at least one byte, at most `len` bytes, from - * the transport medium. Read bytes shall be written in `data`. - * - * - `low_write()` writes at least one byte, at most `len` bytes, unto - * the transport medium. The bytes to write are read from `data`. - * - * - The `len` parameter is never zero, and is always lower than 20000. - * - * - The number of processed bytes (read or written) is returned. Since - * that number is less than 20000, it always fits on an `int`. - * - * - On error, the callbacks return -1. Reaching end-of-stream is an - * error. Errors are permanent: the SSL connection is terminated. - * - * - Callbacks SHOULD NOT return 0. This is tolerated, as long as - * callbacks endeavour to block for some non-negligible amount of - * time until at least one byte can be sent or received (if a - * callback returns 0, then the wrapper invokes it again - * immediately). - * - * - Callbacks MAY return as soon as at least one byte is processed; - * they MAY also insist on reading or writing _all_ requested bytes. - * Since SSL is a self-terminated protocol (each record has a length - * header), this does not change semantics. - * - * - Callbacks need not apply any buffering (for performance) since SSL - * itself uses buffers. - * - * \param ctx wrapper context to initialise. - * \param engine SSL engine to wrap. - * \param low_read callback for reading data from the transport. - * \param read_context context pointer for `low_read()`. - * \param low_write callback for writing data on the transport. - * \param write_context context pointer for `low_write()`. - */ -void br_sslio_init(br_sslio_context *ctx, - br_ssl_engine_context *engine, - int (*low_read)(void *read_context, - unsigned char *data, size_t len), - void *read_context, - int (*low_write)(void *write_context, - const unsigned char *data, size_t len), - void *write_context); - -/** - * \brief Read some application data from a SSL connection. - * - * If `len` is zero, then this function returns 0 immediately. In - * all other cases, it never returns 0. - * - * This call returns only when at least one byte has been obtained. - * Returned value is the number of bytes read, or -1 on error. The - * number of bytes always fits on an 'int' (data from a single SSL/TLS - * record is returned). - * - * On error or SSL closure, this function returns -1. The caller should - * inspect the error status on the SSL engine to distinguish between - * normal closure and error. - * - * \param cc SSL wrapper context. - * \param dst destination buffer for application data. - * \param len maximum number of bytes to obtain. - * \return number of bytes obtained, or -1 on error. - */ -int br_sslio_read(br_sslio_context *cc, void *dst, size_t len); - -/** - * \brief Read application data from a SSL connection. - * - * This calls returns only when _all_ requested `len` bytes are read, - * or an error is reached. Returned value is 0 on success, -1 on error. - * A normal (verified) SSL closure before that many bytes are obtained - * is reported as an error by this function. - * - * \param cc SSL wrapper context. - * \param dst destination buffer for application data. - * \param len number of bytes to obtain. - * \return 0 on success, or -1 on error. - */ -int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len); - -#ifdef ARDUINO -int br_sslio_read_available(br_sslio_context *cc); -int br_sslio_peek(br_sslio_context *cc, void *dst, size_t len); -#endif - -/** - * \brief Write some application data unto a SSL connection. - * - * If `len` is zero, then this function returns 0 immediately. In - * all other cases, it never returns 0. - * - * This call returns only when at least one byte has been written. - * Returned value is the number of bytes written, or -1 on error. The - * number of bytes always fits on an 'int' (less than 20000). - * - * On error or SSL closure, this function returns -1. The caller should - * inspect the error status on the SSL engine to distinguish between - * normal closure and error. - * - * **Important:** SSL is buffered; a "written" byte is a byte that was - * injected into the wrapped SSL engine, but this does not necessarily mean - * that it has been scheduled for sending. Use `br_sslio_flush()` to - * ensure that all pending data has been sent to the transport medium. - * - * \param cc SSL wrapper context. - * \param src source buffer for application data. - * \param len maximum number of bytes to write. - * \return number of bytes written, or -1 on error. - */ -int br_sslio_write(br_sslio_context *cc, const void *src, size_t len); - -/** - * \brief Write application data unto a SSL connection. - * - * This calls returns only when _all_ requested `len` bytes have been - * written, or an error is reached. Returned value is 0 on success, -1 - * on error. A normal (verified) SSL closure before that many bytes are - * written is reported as an error by this function. - * - * **Important:** SSL is buffered; a "written" byte is a byte that was - * injected into the wrapped SSL engine, but this does not necessarily mean - * that it has been scheduled for sending. Use `br_sslio_flush()` to - * ensure that all pending data has been sent to the transport medium. - * - * \param cc SSL wrapper context. - * \param src source buffer for application data. - * \param len number of bytes to write. - * \return 0 on success, or -1 on error. - */ -int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len); - -/** - * \brief Flush pending data. - * - * This call makes sure that any buffered application data in the - * provided context (including the wrapped SSL engine) has been sent - * to the transport medium (i.e. accepted by the `low_write()` callback - * method). If there is no such pending data, then this function does - * nothing (and returns a success, i.e. 0). - * - * If the underlying transport medium has its own buffers, then it is - * up to the caller to ensure the corresponding flushing. - * - * Returned value is 0 on success, -1 on error. - * - * \param cc SSL wrapper context. - * \return 0 on success, or -1 on error. - */ -int br_sslio_flush(br_sslio_context *cc); - -/** - * \brief Close the SSL connection. - * - * This call runs the SSL closure protocol (sending a `close_notify`, - * receiving the response `close_notify`). When it returns, the SSL - * connection is finished. It is still up to the caller to manage the - * possible transport-level termination, if applicable (alternatively, - * the underlying transport stream may be reused for non-SSL messages). - * - * Returned value is 0 on success, -1 on error. A failure by the peer - * to process the complete closure protocol (i.e. sending back the - * `close_notify`) is an error. - * - * \param cc SSL wrapper context. - * \return 0 on success, or -1 on error. - */ -int br_sslio_close(br_sslio_context *cc); - -/* ===================================================================== */ - -/* - * Symbolic constants for cipher suites. - */ - -/* From RFC 5246 */ -#define BR_TLS_NULL_WITH_NULL_NULL 0x0000 -#define BR_TLS_RSA_WITH_NULL_MD5 0x0001 -#define BR_TLS_RSA_WITH_NULL_SHA 0x0002 -#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B -#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004 -#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005 -#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A -#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F -#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 -#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C -#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D -#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D -#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 -#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 -#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 -#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 -#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 -#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 -#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 -#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 -#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 -#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 -#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 -#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E -#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F -#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040 -#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067 -#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068 -#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069 -#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A -#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B -#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018 -#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B -#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 -#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A -#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C -#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D - -/* From RFC 4492 */ -#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 -#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 -#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 -#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 -#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 -#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 -#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 -#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 -#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 -#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A -#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B -#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C -#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D -#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E -#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F -#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 -#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 -#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 -#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 -#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 -#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015 -#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016 -#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017 -#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 -#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 - -/* From RFC 5288 */ -#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C -#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D -#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E -#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F -#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0 -#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1 -#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2 -#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3 -#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4 -#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5 -#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6 -#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7 - -/* From RFC 5289 */ -#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 -#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 -#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 -#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 -#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 -#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 -#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 -#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A -#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B -#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C -#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D -#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E -#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F -#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 -#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 -#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 - -/* From RFC 6655 and 7251 */ -#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C -#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D -#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 -#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 -#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC -#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD -#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE -#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF - -/* From RFC 7905 */ -#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 -#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 -#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA -#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB -#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC -#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD -#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE - -/* From RFC 7507 */ -#define BR_TLS_FALLBACK_SCSV 0x5600 - -/* - * Symbolic constants for alerts. - */ -#define BR_ALERT_CLOSE_NOTIFY 0 -#define BR_ALERT_UNEXPECTED_MESSAGE 10 -#define BR_ALERT_BAD_RECORD_MAC 20 -#define BR_ALERT_RECORD_OVERFLOW 22 -#define BR_ALERT_DECOMPRESSION_FAILURE 30 -#define BR_ALERT_HANDSHAKE_FAILURE 40 -#define BR_ALERT_BAD_CERTIFICATE 42 -#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43 -#define BR_ALERT_CERTIFICATE_REVOKED 44 -#define BR_ALERT_CERTIFICATE_EXPIRED 45 -#define BR_ALERT_CERTIFICATE_UNKNOWN 46 -#define BR_ALERT_ILLEGAL_PARAMETER 47 -#define BR_ALERT_UNKNOWN_CA 48 -#define BR_ALERT_ACCESS_DENIED 49 -#define BR_ALERT_DECODE_ERROR 50 -#define BR_ALERT_DECRYPT_ERROR 51 -#define BR_ALERT_PROTOCOL_VERSION 70 -#define BR_ALERT_INSUFFICIENT_SECURITY 71 -#define BR_ALERT_INTERNAL_ERROR 80 -#define BR_ALERT_USER_CANCELED 90 -#define BR_ALERT_NO_RENEGOTIATION 100 -#define BR_ALERT_UNSUPPORTED_EXTENSION 110 -#define BR_ALERT_NO_APPLICATION_PROTOCOL 120 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/bearssl_x509.h b/src/tls/bearssl/bearssl_x509.h deleted file mode 100644 index 49d2fba0d..000000000 --- a/src/tls/bearssl/bearssl_x509.h +++ /dev/null @@ -1,1397 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef BR_BEARSSL_X509_H__ -#define BR_BEARSSL_X509_H__ - -#include -#include - -#include "bearssl_ec.h" -#include "bearssl_hash.h" -#include "bearssl_rsa.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** \file bearssl_x509.h - * - * # X.509 Certificate Chain Processing - * - * An X.509 processing engine receives an X.509 chain, chunk by chunk, - * as received from a SSL/TLS client or server (the client receives the - * server's certificate chain, and the server receives the client's - * certificate chain if it requested a client certificate). The chain - * is thus injected in the engine in SSL order (end-entity first). - * - * The engine's job is to return the public key to use for SSL/TLS. - * How exactly that key is obtained and verified is entirely up to the - * engine. - * - * **The "known key" engine** returns a public key which is already known - * from out-of-band information (e.g. the client _remembers_ the key from - * a previous connection, as in the usual SSH model). This is the simplest - * engine since it simply ignores the chain, thereby avoiding the need - * for any decoding logic. - * - * **The "minimal" engine** implements minimal X.509 decoding and chain - * validation: - * - * - The provided chain should validate "as is". There is no attempt - * at reordering, skipping or downloading extra certificates. - * - * - X.509 v1, v2 and v3 certificates are supported. - * - * - Trust anchors are a DN and a public key. Each anchor is either a - * "CA" anchor, or a non-CA. - * - * - If the end-entity certificate matches a non-CA anchor (subject DN - * is equal to the non-CA name, and public key is also identical to - * the anchor key), then this is a _direct trust_ case and the - * remaining certificates are ignored. - * - * - Unless direct trust is applied, the chain must be verifiable up to - * a certificate whose issuer DN matches the DN from a "CA" trust anchor, - * and whose signature is verifiable against that anchor's public key. - * Subsequent certificates in the chain are ignored. - * - * - The engine verifies subject/issuer DN matching, and enforces - * processing of Basic Constraints and Key Usage extensions. The - * Authority Key Identifier, Subject Key Identifier, Issuer Alt Name, - * Subject Directory Attribute, CRL Distribution Points, Freshest CRL, - * Authority Info Access and Subject Info Access extensions are - * ignored. The Subject Alt Name is decoded for the end-entity - * certificate under some conditions (see below). Other extensions - * are ignored if non-critical, or imply chain rejection if critical. - * - * - The Subject Alt Name extension is parsed for names of type `dNSName` - * when decoding the end-entity certificate, and only if there is a - * server name to match. If there is no SAN extension, then the - * Common Name from the subjectDN is used. That name matching is - * case-insensitive and honours a single starting wildcard (i.e. if - * the name in the certificate starts with "`*.`" then this matches - * any word as first element). Note: this name matching is performed - * also in the "direct trust" model. - * - * - DN matching is byte-to-byte equality (a future version might - * include some limited processing for case-insensitive matching and - * whitespace normalisation). - * - * - Successful validation produces a public key type but also a set - * of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). - * The caller is responsible for checking that the key type and - * usages are compatible with the expected values (e.g. with the - * selected cipher suite, when the client validates the server's - * certificate). - * - * **Important caveats:** - * - * - The "minimal" engine does not check revocation status. The relevant - * extensions are ignored, and CRL or OCSP responses are not gathered - * or checked. - * - * - The "minimal" engine does not currently support Name Constraints - * (some basic functionality to handle sub-domains may be added in a - * later version). - * - * - The decoder is not "validating" in the sense that it won't reject - * some certificates with invalid field values when these fields are - * not actually processed. - */ - -/* - * X.509 error codes are in the 32..63 range. - */ - -/** \brief X.509 status: validation was successful; this is not actually - an error. */ -#define BR_ERR_X509_OK 32 - -/** \brief X.509 status: invalid value in an ASN.1 structure. */ -#define BR_ERR_X509_INVALID_VALUE 33 - -/** \brief X.509 status: truncated certificate. */ -#define BR_ERR_X509_TRUNCATED 34 - -/** \brief X.509 status: empty certificate chain (no certificate at all). */ -#define BR_ERR_X509_EMPTY_CHAIN 35 - -/** \brief X.509 status: decoding error: inner element extends beyond - outer element size. */ -#define BR_ERR_X509_INNER_TRUNC 36 - -/** \brief X.509 status: decoding error: unsupported tag class (application - or private). */ -#define BR_ERR_X509_BAD_TAG_CLASS 37 - -/** \brief X.509 status: decoding error: unsupported tag value. */ -#define BR_ERR_X509_BAD_TAG_VALUE 38 - -/** \brief X.509 status: decoding error: indefinite length. */ -#define BR_ERR_X509_INDEFINITE_LENGTH 39 - -/** \brief X.509 status: decoding error: extraneous element. */ -#define BR_ERR_X509_EXTRA_ELEMENT 40 - -/** \brief X.509 status: decoding error: unexpected element. */ -#define BR_ERR_X509_UNEXPECTED 41 - -/** \brief X.509 status: decoding error: expected constructed element, but - is primitive. */ -#define BR_ERR_X509_NOT_CONSTRUCTED 42 - -/** \brief X.509 status: decoding error: expected primitive element, but - is constructed. */ -#define BR_ERR_X509_NOT_PRIMITIVE 43 - -/** \brief X.509 status: decoding error: BIT STRING length is not multiple - of 8. */ -#define BR_ERR_X509_PARTIAL_BYTE 44 - -/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */ -#define BR_ERR_X509_BAD_BOOLEAN 45 - -/** \brief X.509 status: decoding error: value is off-limits. */ -#define BR_ERR_X509_OVERFLOW 46 - -/** \brief X.509 status: invalid distinguished name. */ -#define BR_ERR_X509_BAD_DN 47 - -/** \brief X.509 status: invalid date/time representation. */ -#define BR_ERR_X509_BAD_TIME 48 - -/** \brief X.509 status: certificate contains unsupported features that - cannot be ignored. */ -#define BR_ERR_X509_UNSUPPORTED 49 - -/** \brief X.509 status: key or signature size exceeds internal limits. */ -#define BR_ERR_X509_LIMIT_EXCEEDED 50 - -/** \brief X.509 status: key type does not match that which was expected. */ -#define BR_ERR_X509_WRONG_KEY_TYPE 51 - -/** \brief X.509 status: signature is invalid. */ -#define BR_ERR_X509_BAD_SIGNATURE 52 - -/** \brief X.509 status: validation time is unknown. */ -#define BR_ERR_X509_TIME_UNKNOWN 53 - -/** \brief X.509 status: certificate is expired or not yet valid. */ -#define BR_ERR_X509_EXPIRED 54 - -/** \brief X.509 status: issuer/subject DN mismatch in the chain. */ -#define BR_ERR_X509_DN_MISMATCH 55 - -/** \brief X.509 status: expected server name was not found in the chain. */ -#define BR_ERR_X509_BAD_SERVER_NAME 56 - -/** \brief X.509 status: unknown critical extension in certificate. */ -#define BR_ERR_X509_CRITICAL_EXTENSION 57 - -/** \brief X.509 status: not a CA, or path length constraint violation */ -#define BR_ERR_X509_NOT_CA 58 - -/** \brief X.509 status: Key Usage extension prohibits intended usage. */ -#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59 - -/** \brief X.509 status: public key found in certificate is too small. */ -#define BR_ERR_X509_WEAK_PUBLIC_KEY 60 - -/** \brief X.509 status: chain could not be linked to a trust anchor. */ -#define BR_ERR_X509_NOT_TRUSTED 62 - -/** - * \brief Aggregate structure for public keys. - */ -typedef struct { - /** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */ - unsigned char key_type; - /** \brief Actual public key. */ - union { - /** \brief RSA public key. */ - br_rsa_public_key rsa; - /** \brief EC public key. */ - br_ec_public_key ec; - } key; -} br_x509_pkey; - -/** - * \brief Distinguished Name (X.500) structure. - * - * The DN is DER-encoded. - */ -typedef struct { - /** \brief Encoded DN data. */ - unsigned char *data; - /** \brief Encoded DN length (in bytes). */ - size_t len; -} br_x500_name; - -/** - * \brief Trust anchor structure. - */ -typedef struct { - /** \brief Encoded DN (X.500 name). */ - br_x500_name dn; - /** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */ - unsigned flags; - /** \brief Anchor public key. */ - br_x509_pkey pkey; -} br_x509_trust_anchor; - -/** - * \brief Trust anchor flag: CA. - * - * A "CA" anchor is deemed fit to verify signatures on certificates. - * A "non-CA" anchor is accepted only for direct trust (server's - * certificate name and key match the anchor). - */ -#define BR_X509_TA_CA 0x0001 - -/* - * Key type: combination of a basic key type (low 4 bits) and some - * optional flags. - * - * For a public key, the basic key type only is set. - * - * For an expected key type, the flags indicate the intended purpose(s) - * for the key; the basic key type may be set to 0 to indicate that any - * key type compatible with the indicated purpose is acceptable. - */ -/** \brief Key type: algorithm is RSA. */ -#define BR_KEYTYPE_RSA 1 -/** \brief Key type: algorithm is EC. */ -#define BR_KEYTYPE_EC 2 - -/** - * \brief Key type: usage is "key exchange". - * - * This value is combined (with bitwise OR) with the algorithm - * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 - * validation engine that it should find a public key of that type, - * fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher - * suites). - */ -#define BR_KEYTYPE_KEYX 0x10 - -/** - * \brief Key type: usage is "signature". - * - * This value is combined (with bitwise OR) with the algorithm - * (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509 - * validation engine that it should find a public key of that type, - * fit for signatures (e.g. `TLS_ECDHE_*` cipher suites). - */ -#define BR_KEYTYPE_SIGN 0x20 - -/* - * start_chain Called when a new chain is started. If 'server_name' - * is not NULL and non-empty, then it is a name that - * should be looked for in the EE certificate (in the - * SAN extension as dNSName, or in the subjectDN's CN - * if there is no SAN extension). - * The caller ensures that the provided 'server_name' - * pointer remains valid throughout validation. - * - * start_cert Begins a new certificate in the chain. The provided - * length is in bytes; this is the total certificate length. - * - * append Get some additional bytes for the current certificate. - * - * end_cert Ends the current certificate. - * - * end_chain Called at the end of the chain. Returned value is - * 0 on success, or a non-zero error code. - * - * get_pkey Returns the EE certificate public key. - * - * For a complete chain, start_chain() and end_chain() are always - * called. For each certificate, start_cert(), some append() calls, then - * end_cert() are called, in that order. There may be no append() call - * at all if the certificate is empty (which is not valid but may happen - * if the peer sends exactly that). - * - * get_pkey() shall return a pointer to a structure that is valid as - * long as a new chain is not started. This may be a sub-structure - * within the context for the engine. This function MAY return a valid - * pointer to a public key even in some cases of validation failure, - * depending on the validation engine. - */ - -/** - * \brief Class type for an X.509 engine. - * - * A certificate chain validation uses a caller-allocated context, which - * contains the running state for that validation. Methods are called - * in due order: - * - * - `start_chain()` is called at the start of the validation. - * - Certificates are processed one by one, in SSL order (end-entity - * comes first). For each certificate, the following methods are - * called: - * - * - `start_cert()` at the beginning of the certificate. - * - `append()` is called zero, one or more times, to provide - * the certificate (possibly in chunks). - * - `end_cert()` at the end of the certificate. - * - * - `end_chain()` is called when the last certificate in the chain - * was processed. - * - `get_pkey()` is called after chain processing, if the chain - * validation was successful. - * - * A context structure may be reused; the `start_chain()` method shall - * ensure (re)initialisation. - */ -typedef struct br_x509_class_ br_x509_class; -struct br_x509_class_ { - /** - * \brief X.509 context size, in bytes. - */ - size_t context_size; - - /** - * \brief Start a new chain. - * - * This method shall set the vtable (first field) of the context - * structure. - * - * The `server_name`, if not `NULL`, will be considered as a - * fully qualified domain name, to be matched against the `dNSName` - * elements of the end-entity certificate's SAN extension (if there - * is no SAN, then the Common Name from the subjectDN will be used). - * If `server_name` is `NULL` then no such matching is performed. - * - * \param ctx validation context. - * \param server_name server name to match (or `NULL`). - */ - void (*start_chain)(const br_x509_class **ctx, - const char *server_name); - - /** - * \brief Start a new certificate. - * - * \param ctx validation context. - * \param length new certificate length (in bytes). - */ - void (*start_cert)(const br_x509_class **ctx, uint32_t length); - - /** - * \brief Receive some bytes for the current certificate. - * - * This function may be called several times in succession for - * a given certificate. The caller guarantees that for each - * call, `len` is not zero, and the sum of all chunk lengths - * for a certificate matches the total certificate length which - * was provided in the previous `start_cert()` call. - * - * If the new certificate is empty (no byte at all) then this - * function won't be called at all. - * - * \param ctx validation context. - * \param buf certificate data chunk. - * \param len certificate data chunk length (in bytes). - */ - void (*append)(const br_x509_class **ctx, - const unsigned char *buf, size_t len); - - /** - * \brief Finish the current certificate. - * - * This function is called when the end of the current certificate - * is reached. - * - * \param ctx validation context. - */ - void (*end_cert)(const br_x509_class **ctx); - - /** - * \brief Finish the chain. - * - * This function is called at the end of the chain. It shall - * return either 0 if the validation was successful, or a - * non-zero error code. The `BR_ERR_X509_*` constants are - * error codes, though other values may be possible. - * - * \param ctx validation context. - * \return 0 on success, or a non-zero error code. - */ - unsigned (*end_chain)(const br_x509_class **ctx); - - /** - * \brief Get the resulting end-entity public key. - * - * The decoded public key is returned. The returned pointer - * may be valid only as long as the context structure is - * unmodified, i.e. it may cease to be valid if the context - * is released or reused. - * - * This function _may_ return `NULL` if the validation failed. - * However, returning a public key does not mean that the - * validation was wholly successful; some engines may return - * a decoded public key even if the chain did not end on a - * trusted anchor. - * - * If validation succeeded and `usage` is not `NULL`, then - * `*usage` is filled with a combination of `BR_KEYTYPE_SIGN` - * and/or `BR_KEYTYPE_KEYX` that specifies the validated key - * usage types. It is the caller's responsibility to check - * that value against the intended use of the public key. - * - * \param ctx validation context. - * \return the end-entity public key, or `NULL`. - */ - const br_x509_pkey *(*get_pkey)( - const br_x509_class *const *ctx, unsigned *usages); -}; - -/** - * \brief The "known key" X.509 engine structure. - * - * The structure contents are opaque (they shall not be accessed directly), - * except for the first field (the vtable). - * - * The "known key" engine returns an externally configured public key, - * and totally ignores the certificate contents. - */ -typedef struct { - /** \brief Reference to the context vtable. */ - const br_x509_class *vtable; -#ifndef BR_DOXYGEN_IGNORE - br_x509_pkey pkey; - unsigned usages; -#endif -} br_x509_knownkey_context; - -/** - * \brief Class instance for the "known key" X.509 engine. - */ -extern const br_x509_class br_x509_knownkey_vtable; - -/** - * \brief Initialize a "known key" X.509 engine with a known RSA public key. - * - * The `usages` parameter indicates the allowed key usages for that key - * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). - * - * The provided pointers are linked in, not copied, so they must remain - * valid while the public key may be in usage. - * - * \param ctx context to initialise. - * \param pk known public key. - * \param usages allowed key usages. - */ -void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, - const br_rsa_public_key *pk, unsigned usages); - -/** - * \brief Initialize a "known key" X.509 engine with a known EC public key. - * - * The `usages` parameter indicates the allowed key usages for that key - * (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`). - * - * The provided pointers are linked in, not copied, so they must remain - * valid while the public key may be in usage. - * - * \param ctx context to initialise. - * \param pk known public key. - * \param usages allowed key usages. - */ -void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, - const br_ec_public_key *pk, unsigned usages); - -#ifndef BR_DOXYGEN_IGNORE -/* - * The minimal X.509 engine has some state buffers which must be large - * enough to simultaneously accommodate: - * -- the public key extracted from the current certificate; - * -- the signature on the current certificate or on the previous - * certificate; - * -- the public key extracted from the EE certificate. - * - * We store public key elements in their raw unsigned big-endian - * encoding. We want to support up to RSA-4096 with a short (up to 64 - * bits) public exponent, thus a buffer for a public key must have - * length at least 520 bytes. Similarly, a RSA-4096 signature has length - * 512 bytes. - * - * Though RSA public exponents can formally be as large as the modulus - * (mathematically, even larger exponents would work, but PKCS#1 forbids - * them), exponents that do not fit on 32 bits are extremely rare, - * notably because some widespread implementations (e.g. Microsoft's - * CryptoAPI) don't support them. Moreover, large public exponent do not - * seem to imply any tangible security benefit, and they increase the - * cost of public key operations. The X.509 "minimal" engine will tolerate - * public exponents of arbitrary size as long as the modulus and the - * exponent can fit together in the dedicated buffer. - * - * EC public keys are shorter than RSA public keys; even with curve - * NIST P-521 (the largest curve we care to support), a public key is - * encoded over 133 bytes only. - */ -#define BR_X509_BUFSIZE_KEY 520 -#define BR_X509_BUFSIZE_SIG 512 -#endif - -/** - * \brief Type for receiving a name element. - * - * An array of such structures can be provided to the X.509 decoding - * engines. If the specified elements are found in the certificate - * subject DN or the SAN extension, then the name contents are copied - * as zero-terminated strings into the buffer. - * - * The decoder converts TeletexString and BMPString to UTF8String, and - * ensures that the resulting string is zero-terminated. If the string - * does not fit in the provided buffer, then the copy is aborted and an - * error is reported. - */ -typedef struct { - /** - * \brief Element OID. - * - * For X.500 name elements (to be extracted from the subject DN), - * this is the encoded OID for the requested name element; the - * first byte shall contain the length of the DER-encoded OID - * value, followed by the OID value (for instance, OID 2.5.4.3, - * for id-at-commonName, will be `03 55 04 03`). This is - * equivalent to full DER encoding with the length but without - * the tag. - * - * For SAN name elements, the first byte (`oid[0]`) has value 0, - * followed by another byte that matches the expected GeneralName - * tag. Allowed second byte values are then: - * - * - 1: `rfc822Name` - * - * - 2: `dNSName` - * - * - 6: `uniformResourceIdentifier` - * - * - 0: `otherName` - * - * If first and second byte are 0, then this is a SAN element of - * type `otherName`; the `oid[]` array should then contain, right - * after the two bytes of value 0, an encoded OID (with the same - * conventions as for X.500 name elements). If a match is found - * for that OID, then the corresponding name element will be - * extracted, as long as it is a supported string type. - */ - const unsigned char *oid; - - /** - * \brief Destination buffer. - */ - char *buf; - - /** - * \brief Length (in bytes) of the destination buffer. - * - * The buffer MUST NOT be smaller than 1 byte. - */ - size_t len; - - /** - * \brief Decoding status. - * - * Status is 0 if the name element was not found, 1 if it was - * found and decoded, or -1 on error. Error conditions include - * an unrecognised encoding, an invalid encoding, or a string - * too large for the destination buffer. - */ - int status; - -} br_name_element; - -/** - * \brief The "minimal" X.509 engine structure. - * - * The structure contents are opaque (they shall not be accessed directly), - * except for the first field (the vtable). - * - * The "minimal" engine performs a rudimentary but serviceable X.509 path - * validation. - */ -typedef struct { - const br_x509_class *vtable; - -#ifndef BR_DOXYGEN_IGNORE - /* Structure for returning the EE public key. */ - br_x509_pkey pkey; - - /* CPU for the T0 virtual machine. */ - struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; - } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; - int err; - - /* Server name to match with the SAN / CN of the EE certificate. */ - const char *server_name; - - /* Validated key usages. */ - unsigned char key_usages; - - /* Explicitly set date and time. */ - uint32_t days, seconds; - - /* Current certificate length (in bytes). Set to 0 when the - certificate has been fully processed. */ - uint32_t cert_length; - - /* Number of certificates processed so far in the current chain. - It is incremented at the end of the processing of a certificate, - so it is 0 for the EE. */ - uint32_t num_certs; - - /* Certificate data chunk. */ - const unsigned char *hbuf; - size_t hlen; - - /* The pad serves as destination for various operations. */ - unsigned char pad[256]; - - /* Buffer for EE public key data. */ - unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY]; - - /* Buffer for currently decoded public key. */ - unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; - - /* Signature type: signer key type, offset to the hash - function OID (in the T0 data block) and hash function - output length (TBS hash length). */ - unsigned char cert_signer_key_type; - uint16_t cert_sig_hash_oid; - unsigned char cert_sig_hash_len; - - /* Current/last certificate signature. */ - unsigned char cert_sig[BR_X509_BUFSIZE_SIG]; - uint16_t cert_sig_len; - - /* Minimum RSA key length (difference in bytes from 128). */ - int16_t min_rsa_size; - - /* Configured trust anchors. */ - const br_x509_trust_anchor *trust_anchors; - size_t trust_anchors_num; - - /* - * Multi-hasher for the TBS. - */ - unsigned char do_mhash; - br_multihash_context mhash; - unsigned char tbs_hash[64]; - - /* - * Simple hasher for the subject/issuer DN. - */ - unsigned char do_dn_hash; - const br_hash_class *dn_hash_impl; - br_hash_compat_context dn_hash; - unsigned char current_dn_hash[64]; - unsigned char next_dn_hash[64]; - unsigned char saved_dn_hash[64]; - - /* - * Name elements to gather. - */ - br_name_element *name_elts; - size_t num_name_elts; - - /* - * Public key cryptography implementations (signature verification). - */ - br_rsa_pkcs1_vrfy irsa; - br_ecdsa_vrfy iecdsa; - const br_ec_impl *iec; -#endif - -} br_x509_minimal_context; - -/** - * \brief Class instance for the "minimal" X.509 engine. - */ -extern const br_x509_class br_x509_minimal_vtable; - -/** - * \brief Initialise a "minimal" X.509 engine. - * - * The `dn_hash_impl` parameter shall be a hash function internally used - * to match X.500 names (subject/issuer DN, and anchor names). Any standard - * hash function may be used, but a collision-resistant hash function is - * advised. - * - * After initialization, some implementations for signature verification - * (hash functions and signature algorithms) MUST be added. - * - * \param ctx context to initialise. - * \param dn_hash_impl hash function for DN comparisons. - * \param trust_anchors trust anchors. - * \param trust_anchors_num number of trust anchors. - */ -void br_x509_minimal_init(br_x509_minimal_context *ctx, - const br_hash_class *dn_hash_impl, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); - -/** - * \brief Set a supported hash function in an X.509 "minimal" engine. - * - * Hash functions are used with signature verification algorithms. - * Once initialised (with `br_x509_minimal_init()`), the context must - * be configured with the hash functions it shall support for that - * purpose. The hash function identifier MUST be one of the standard - * hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256, - * SHA-384 and SHA-512). - * - * If `impl` is `NULL`, this _removes_ support for the designated - * hash function. - * - * \param ctx validation context. - * \param id hash function identifier (from 1 to 6). - * \param impl hash function implementation (or `NULL`). - */ -static inline void -br_x509_minimal_set_hash(br_x509_minimal_context *ctx, - int id, const br_hash_class *impl) -{ - br_multihash_setimpl(&ctx->mhash, id, impl); -} - -/** - * \brief Set a RSA signature verification implementation in the X.509 - * "minimal" engine. - * - * Once initialised (with `br_x509_minimal_init()`), the context must - * be configured with the signature verification implementations that - * it is supposed to support. If `irsa` is `0`, then the RSA support - * is disabled. - * - * \param ctx validation context. - * \param irsa RSA signature verification implementation (or `0`). - */ -static inline void -br_x509_minimal_set_rsa(br_x509_minimal_context *ctx, - br_rsa_pkcs1_vrfy irsa) -{ - ctx->irsa = irsa; -} - -/** - * \brief Set a ECDSA signature verification implementation in the X.509 - * "minimal" engine. - * - * Once initialised (with `br_x509_minimal_init()`), the context must - * be configured with the signature verification implementations that - * it is supposed to support. - * - * If `iecdsa` is `0`, then this call disables ECDSA support; in that - * case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function - * that verifies ECDSA signatures with format "asn1", and it will use - * `iec` as underlying elliptic curve support. - * - * \param ctx validation context. - * \param iec elliptic curve implementation (or `NULL`). - * \param iecdsa ECDSA implementation (or `0`). - */ -static inline void -br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, - const br_ec_impl *iec, br_ecdsa_vrfy iecdsa) -{ - ctx->iecdsa = iecdsa; - ctx->iec = iec; -} - -/** - * \brief Initialise a "minimal" X.509 engine with default algorithms. - * - * This function performs the same job as `br_x509_minimal_init()`, but - * also sets implementations for RSA, ECDSA, and the standard hash - * functions. - * - * \param ctx context to initialise. - * \param trust_anchors trust anchors. - * \param trust_anchors_num number of trust anchors. - */ -void br_x509_minimal_init_full(br_x509_minimal_context *ctx, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); - -/** - * \brief Set the validation time for the X.509 "minimal" engine. - * - * The validation time is set as two 32-bit integers, for days and - * seconds since a fixed epoch: - * - * - Days are counted in a proleptic Gregorian calendar since - * January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD"; - * it is also traditionally known as "1 BC". - * - * - Seconds are counted since midnight, from 0 to 86400 (a count of - * 86400 is possible only if a leap second happened). - * - * The validation date and time is understood in the UTC time zone. - * - * If the validation date and time are not explicitly set, but BearSSL - * was compiled with support for the system clock on the underlying - * platform, then the current time will automatically be used. Otherwise, - * not setting the validation date and time implies a validation - * failure (except in case of direct trust of the EE key). - * - * \param ctx validation context. - * \param days days since January 1st, 0 AD (Gregorian calendar). - * \param seconds seconds since midnight (0 to 86400). - */ -static inline void -br_x509_minimal_set_time(br_x509_minimal_context *ctx, - uint32_t days, uint32_t seconds) -{ - ctx->days = days; - ctx->seconds = seconds; -} - -/** - * \brief Set the minimal acceptable length for RSA keys (X.509 "minimal" - * engine). - * - * The RSA key length is expressed in bytes. The default minimum key - * length is 128 bytes, corresponding to 1017 bits. RSA keys shorter - * than the configured length will be rejected, implying validation - * failure. This setting applies to keys extracted from certificates - * (both end-entity, and intermediate CA) but not to "CA" trust anchors. - * - * \param ctx validation context. - * \param byte_length minimum RSA key length, **in bytes** (not bits). - */ -static inline void -br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) -{ - ctx->min_rsa_size = (int16_t)(byte_length - 128); -} - -/** - * \brief Set the name elements to gather. - * - * The provided array is linked in the context. The elements are - * gathered from the EE certificate. If the same element type is - * requested several times, then the relevant structures will be filled - * in the order the matching values are encountered in the certificate. - * - * \param ctx validation context. - * \param elts array of name element structures to fill. - * \param num_elts number of name element structures to fill. - */ -static inline void -br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, - br_name_element *elts, size_t num_elts) -{ - ctx->name_elts = elts; - ctx->num_name_elts = num_elts; -} - -/** - * \brief X.509 decoder context. - * - * This structure is _not_ for X.509 validation, but for extracting - * names and public keys from encoded certificates. Intended usage is - * to use (self-signed) certificates as trust anchors. - * - * Contents are opaque and shall not be accessed directly. - */ -typedef struct { - -#ifndef BR_DOXYGEN_IGNORE - /* Structure for returning the public key. */ - br_x509_pkey pkey; - - /* CPU for the T0 virtual machine. */ - struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; - } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; - int err; - - /* The pad serves as destination for various operations. */ - unsigned char pad[256]; - - /* Flag set when decoding succeeds. */ - unsigned char decoded; - - /* Validity dates. */ - uint32_t notbefore_days, notbefore_seconds; - uint32_t notafter_days, notafter_seconds; - - /* The "CA" flag. This is set to true if the certificate contains - a Basic Constraints extension that asserts CA status. */ - unsigned char isCA; - - /* DN processing: the subject DN is extracted and pushed to the - provided callback. */ - unsigned char copy_dn; - void *append_dn_ctx; - void (*append_dn)(void *ctx, const void *buf, size_t len); - - /* Certificate data chunk. */ - const unsigned char *hbuf; - size_t hlen; - - /* Buffer for decoded public key. */ - unsigned char pkey_data[BR_X509_BUFSIZE_KEY]; - - /* Type of key and hash function used in the certificate signature. */ - unsigned char signer_key_type; - unsigned char signer_hash_id; -#endif - -} br_x509_decoder_context; - -/** - * \brief Initialise an X.509 decoder context for processing a new - * certificate. - * - * The `append_dn()` callback (with opaque context `append_dn_ctx`) - * will be invoked to receive, chunk by chunk, the certificate's - * subject DN. If `append_dn` is `0` then the subject DN will be - * ignored. - * - * \param ctx X.509 decoder context to initialise. - * \param append_dn DN receiver callback (or `0`). - * \param append_dn_ctx context for the DN receiver callback. - */ -void br_x509_decoder_init(br_x509_decoder_context *ctx, - void (*append_dn)(void *ctx, const void *buf, size_t len), - void *append_dn_ctx); - -/** - * \brief Push some certificate bytes into a decoder context. - * - * If `len` is non-zero, then that many bytes are pushed, from address - * `data`, into the provided decoder context. - * - * \param ctx X.509 decoder context. - * \param data certificate data chunk. - * \param len certificate data chunk length (in bytes). - */ -void br_x509_decoder_push(br_x509_decoder_context *ctx, - const void *data, size_t len); - -/** - * \brief Obtain the decoded public key. - * - * Returned value is a pointer to a structure internal to the decoder - * context; releasing or reusing the decoder context invalidates that - * structure. - * - * If decoding was not finished, or failed, then `NULL` is returned. - * - * \param ctx X.509 decoder context. - * \return the public key, or `NULL` on unfinished/error. - */ -static inline br_x509_pkey * -br_x509_decoder_get_pkey(br_x509_decoder_context *ctx) -{ - if (ctx->decoded && ctx->err == 0) { - return &ctx->pkey; - } else { - return NULL; - } -} - -/** - * \brief Get decoder error status. - * - * If no error was reported yet but the certificate decoding is not - * finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding - * was successful, then 0 is returned. - * - * \param ctx X.509 decoder context. - * \return 0 on successful decoding, or a non-zero error code. - */ -static inline int -br_x509_decoder_last_error(br_x509_decoder_context *ctx) -{ - if (ctx->err != 0) { - return ctx->err; - } - if (!ctx->decoded) { - return BR_ERR_X509_TRUNCATED; - } - return 0; -} - -/** - * \brief Get the "isCA" flag from an X.509 decoder context. - * - * This flag is set if the decoded certificate claims to be a CA through - * a Basic Constraints extension. This flag should not be read before - * decoding completed successfully. - * - * \param ctx X.509 decoder context. - * \return the "isCA" flag. - */ -static inline int -br_x509_decoder_isCA(br_x509_decoder_context *ctx) -{ - return ctx->isCA; -} - -/** - * \brief Get the issuing CA key type (type of algorithm used to sign the - * decoded certificate). - * - * This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned - * if the signature type was not recognised. - * - * \param ctx X.509 decoder context. - * \return the issuing CA key type. - */ -static inline int -br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx) -{ - return ctx->signer_key_type; -} - -/** - * \brief Get the identifier for the hash function used to sign the decoded - * certificate. - * - * This is 0 if the hash function was not recognised. - * - * \param ctx X.509 decoder context. - * \return the signature hash function identifier. - */ -static inline int -br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx) -{ - return ctx->signer_hash_id; -} - -/** - * \brief Type for an X.509 certificate (DER-encoded). - */ -typedef struct { - /** \brief The DER-encoded certificate data. */ - unsigned char *data; - /** \brief The DER-encoded certificate length (in bytes). */ - size_t data_len; -} br_x509_certificate; - -/** - * \brief Private key decoder context. - * - * The private key decoder recognises RSA and EC private keys, either in - * their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8 - * archive (again DER-encoded). - * - * Structure contents are opaque and shall not be accessed directly. - */ -typedef struct { -#ifndef BR_DOXYGEN_IGNORE - /* Structure for returning the private key. */ - union { - br_rsa_private_key rsa; - br_ec_private_key ec; - } key; - - /* CPU for the T0 virtual machine. */ - struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; - } cpu; - uint32_t dp_stack[32]; - uint32_t rp_stack[32]; - int err; - - /* Private key data chunk. */ - const unsigned char *hbuf; - size_t hlen; - - /* The pad serves as destination for various operations. */ - unsigned char pad[256]; - - /* Decoded key type; 0 until decoding is complete. */ - unsigned char key_type; - - /* Buffer for the private key elements. It shall be large enough - to accommodate all elements for a RSA-4096 private key (roughly - five 2048-bit integers, possibly a bit more). */ - unsigned char key_data[3 * BR_X509_BUFSIZE_SIG]; -#endif -} br_skey_decoder_context; - -/** - * \brief Initialise a private key decoder context. - * - * \param ctx key decoder context to initialise. - */ -void br_skey_decoder_init(br_skey_decoder_context *ctx); - -/** - * \brief Push some data bytes into a private key decoder context. - * - * If `len` is non-zero, then that many data bytes, starting at address - * `data`, are pushed into the decoder. - * - * \param ctx key decoder context. - * \param data private key data chunk. - * \param len private key data chunk length (in bytes). - */ -void br_skey_decoder_push(br_skey_decoder_context *ctx, - const void *data, size_t len); - -/** - * \brief Get the decoding status for a private key. - * - * Decoding status is 0 on success, or a non-zero error code. If the - * decoding is unfinished when this function is called, then the - * status code `BR_ERR_X509_TRUNCATED` is returned. - * - * \param ctx key decoder context. - * \return 0 on successful decoding, or a non-zero error code. - */ -static inline int -br_skey_decoder_last_error(const br_skey_decoder_context *ctx) -{ - if (ctx->err != 0) { - return ctx->err; - } - if (ctx->key_type == 0) { - return BR_ERR_X509_TRUNCATED; - } - return 0; -} - -/** - * \brief Get the decoded private key type. - * - * Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is - * not finished or failed, then 0 is returned. - * - * \param ctx key decoder context. - * \return decoded private key type, or 0. - */ -static inline int -br_skey_decoder_key_type(const br_skey_decoder_context *ctx) -{ - if (ctx->err == 0) { - return ctx->key_type; - } else { - return 0; - } -} - -/** - * \brief Get the decoded RSA private key. - * - * This function returns `NULL` if the decoding failed, or is not - * finished, or the key is not RSA. The returned pointer references - * structures within the context that can become invalid if the context - * is reused or released. - * - * \param ctx key decoder context. - * \return decoded RSA private key, or `NULL`. - */ -static inline const br_rsa_private_key * -br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx) -{ - if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) { - return &ctx->key.rsa; - } else { - return NULL; - } -} - -/** - * \brief Get the decoded EC private key. - * - * This function returns `NULL` if the decoding failed, or is not - * finished, or the key is not EC. The returned pointer references - * structures within the context that can become invalid if the context - * is reused or released. - * - * \param ctx key decoder context. - * \return decoded EC private key, or `NULL`. - */ -static inline const br_ec_private_key * -br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) -{ - if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) { - return &ctx->key.ec; - } else { - return NULL; - } -} - -/** - * \brief Encode an RSA private key (raw DER format). - * - * This function encodes the provided key into the "raw" format specified - * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER - * encoding rules. - * - * The key elements are: - * - * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) - * - * - `pk`: the public key (`n` and `e`) - * - * - `d` (size: `dlen` bytes): the private exponent - * - * The public key elements, and the private exponent `d`, can be - * recomputed from the private key (see `br_rsa_compute_modulus()`, - * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). - * - * If `dest` is not `NULL`, then the encoded key is written at that - * address, and the encoded length (in bytes) is returned. If `dest` is - * `NULL`, then nothing is written, but the encoded length is still - * computed and returned. - * - * \param dest the destination buffer (or `NULL`). - * \param sk the RSA private key. - * \param pk the RSA public key. - * \param d the RSA private exponent. - * \param dlen the RSA private exponent length (in bytes). - * \return the encoded key length (in bytes). - */ -size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, - const br_rsa_public_key *pk, const void *d, size_t dlen); - -/** - * \brief Encode an RSA private key (PKCS#8 DER format). - * - * This function encodes the provided key into the PKCS#8 format - * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" - * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. - * - * The key elements are: - * - * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) - * - * - `pk`: the public key (`n` and `e`) - * - * - `d` (size: `dlen` bytes): the private exponent - * - * The public key elements, and the private exponent `d`, can be - * recomputed from the private key (see `br_rsa_compute_modulus()`, - * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). - * - * If `dest` is not `NULL`, then the encoded key is written at that - * address, and the encoded length (in bytes) is returned. If `dest` is - * `NULL`, then nothing is written, but the encoded length is still - * computed and returned. - * - * \param dest the destination buffer (or `NULL`). - * \param sk the RSA private key. - * \param pk the RSA public key. - * \param d the RSA private exponent. - * \param dlen the RSA private exponent length (in bytes). - * \return the encoded key length (in bytes). - */ -size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, - const br_rsa_public_key *pk, const void *d, size_t dlen); - -/** - * \brief Encode an EC private key (raw DER format). - * - * This function encodes the provided key into the "raw" format specified - * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. - * - * The private key is provided in `sk`, the public key being `pk`. If - * `pk` is `NULL`, then the encoded key will not include the public key - * in its `publicKey` field (which is nominally optional). - * - * If `dest` is not `NULL`, then the encoded key is written at that - * address, and the encoded length (in bytes) is returned. If `dest` is - * `NULL`, then nothing is written, but the encoded length is still - * computed and returned. - * - * If the key cannot be encoded (e.g. because there is no known OBJECT - * IDENTIFIER for the used curve), then 0 is returned. - * - * \param dest the destination buffer (or `NULL`). - * \param sk the EC private key. - * \param pk the EC public key (or `NULL`). - * \return the encoded key length (in bytes), or 0. - */ -size_t br_encode_ec_raw_der(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk); - -/** - * \brief Encode an EC private key (PKCS#8 DER format). - * - * This function encodes the provided key into the PKCS#8 format - * (RFC 5958, type `OneAsymmetricKey`). The curve is identified - * by an OID provided as parameters to the `privateKeyAlgorithm` - * field. The private key value (contents of the `privateKey` field) - * contains the DER encoding of the `ECPrivateKey` type defined in - * RFC 5915, without the `parameters` field (since they would be - * redundant with the information in `privateKeyAlgorithm`). - * - * The private key is provided in `sk`, the public key being `pk`. If - * `pk` is not `NULL`, then the encoded public key is included in the - * `publicKey` field of the private key value (but not in the `publicKey` - * field of the PKCS#8 `OneAsymmetricKey` wrapper). - * - * If `dest` is not `NULL`, then the encoded key is written at that - * address, and the encoded length (in bytes) is returned. If `dest` is - * `NULL`, then nothing is written, but the encoded length is still - * computed and returned. - * - * If the key cannot be encoded (e.g. because there is no known OBJECT - * IDENTIFIER for the used curve), then 0 is returned. - * - * \param dest the destination buffer (or `NULL`). - * \param sk the EC private key. - * \param pk the EC public key (or `NULL`). - * \return the encoded key length (in bytes), or 0. - */ -size_t br_encode_ec_pkcs8_der(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk); - -/** - * \brief PEM banner for RSA private key (raw). - */ -#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" - -/** - * \brief PEM banner for EC private key (raw). - */ -#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" - -/** - * \brief PEM banner for an RSA or EC private key in PKCS#8 format. - */ -#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/tls/bearssl/ccm.c b/src/tls/bearssl/ccm.c deleted file mode 100644 index 7e5c863f0..000000000 --- a/src/tls/bearssl/ccm.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Implementation Notes - * ==================== - * - * The combined CTR + CBC-MAC functions can only handle full blocks, - * so some buffering is necessary. - * - * - 'ptr' contains a value from 0 to 15, which is the number of bytes - * accumulated in buf[] that still needs to be processed with the - * current CBC-MAC computation. - * - * - When processing the message itself, CTR encryption/decryption is - * also done at the same time. The first 'ptr' bytes of buf[] then - * contains the plaintext bytes, while the last '16 - ptr' bytes of - * buf[] are the remnants of the stream block, to be used against - * the next input bytes, when available. When 'ptr' is 0, the - * contents of buf[] are to be ignored. - * - * - The current counter and running CBC-MAC values are kept in 'ctr' - * and 'cbcmac', respectively. - */ - -/* see bearssl_block.h */ -void -br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx) -{ - ctx->bctx = bctx; -} - -/* see bearssl_block.h */ -int -br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len, - uint64_t aad_len, uint64_t data_len, size_t tag_len) -{ - unsigned char tmp[16]; - unsigned u, q; - - if (nonce_len < 7 || nonce_len > 13) { - return 0; - } - if (tag_len < 4 || tag_len > 16 || (tag_len & 1) != 0) { - return 0; - } - q = 15 - (unsigned)nonce_len; - ctx->tag_len = tag_len; - - /* - * Block B0, to start CBC-MAC. - */ - tmp[0] = (aad_len > 0 ? 0x40 : 0x00) - | (((unsigned)tag_len - 2) << 2) - | (q - 1); - memcpy(tmp + 1, nonce, nonce_len); - for (u = 0; u < q; u ++) { - tmp[15 - u] = (unsigned char)data_len; - data_len >>= 8; - } - if (data_len != 0) { - /* - * If the data length was not entirely consumed in the - * loop above, then it exceeds the maximum limit of - * q bytes (when encoded). - */ - return 0; - } - - /* - * Start CBC-MAC. - */ - memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp); - - /* - * Assemble AAD length header. - */ - if ((aad_len >> 32) != 0) { - ctx->buf[0] = 0xFF; - ctx->buf[1] = 0xFF; - br_enc64be(ctx->buf + 2, aad_len); - ctx->ptr = 10; - } else if (aad_len >= 0xFF00) { - ctx->buf[0] = 0xFF; - ctx->buf[1] = 0xFE; - br_enc32be(ctx->buf + 2, (uint32_t)aad_len); - ctx->ptr = 6; - } else if (aad_len > 0) { - br_enc16be(ctx->buf, (unsigned)aad_len); - ctx->ptr = 2; - } else { - ctx->ptr = 0; - } - - /* - * Make initial counter value and compute tag mask. - */ - ctx->ctr[0] = q - 1; - memcpy(ctx->ctr + 1, nonce, nonce_len); - memset(ctx->ctr + 1 + nonce_len, 0, q); - memset(ctx->tagmask, 0, sizeof ctx->tagmask); - (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, - ctx->tagmask, sizeof ctx->tagmask); - - return 1; -} - -/* see bearssl_block.h */ -void -br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len) -{ - const unsigned char *dbuf; - size_t ptr; - - dbuf = data; - - /* - * Complete partial block, if needed. - */ - ptr = ctx->ptr; - if (ptr != 0) { - size_t clen; - - clen = (sizeof ctx->buf) - ptr; - if (clen > len) { - memcpy(ctx->buf + ptr, dbuf, len); - ctx->ptr = ptr + len; - return; - } - memcpy(ctx->buf + ptr, dbuf, clen); - dbuf += clen; - len -= clen; - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, - ctx->buf, sizeof ctx->buf); - } - - /* - * Process complete blocks. - */ - ptr = len & 15; - len -= ptr; - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, dbuf, len); - dbuf += len; - - /* - * Copy last partial block in the context buffer. - */ - memcpy(ctx->buf, dbuf, ptr); - ctx->ptr = ptr; -} - -/* see bearssl_block.h */ -void -br_ccm_flip(br_ccm_context *ctx) -{ - size_t ptr; - - /* - * Complete AAD partial block with zeros, if necessary. - */ - ptr = ctx->ptr; - if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, - ctx->buf, sizeof ctx->buf); - ctx->ptr = 0; - } - - /* - * Counter was already set by br_ccm_reset(). - */ -} - -/* see bearssl_block.h */ -void -br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len) -{ - unsigned char *dbuf; - size_t ptr; - - dbuf = data; - - /* - * Complete a partial block, if any: ctx->buf[] contains - * ctx->ptr plaintext bytes (already reported), and the other - * bytes are CTR stream output. - */ - ptr = ctx->ptr; - if (ptr != 0) { - size_t clen; - size_t u; - - clen = (sizeof ctx->buf) - ptr; - if (clen > len) { - clen = len; - } - if (encrypt) { - for (u = 0; u < clen; u ++) { - unsigned w, x; - - w = ctx->buf[ptr + u]; - x = dbuf[u]; - ctx->buf[ptr + u] = x; - dbuf[u] = w ^ x; - } - } else { - for (u = 0; u < clen; u ++) { - unsigned w; - - w = ctx->buf[ptr + u] ^ dbuf[u]; - dbuf[u] = w; - ctx->buf[ptr + u] = w; - } - } - dbuf += clen; - len -= clen; - ptr += clen; - if (ptr < sizeof ctx->buf) { - ctx->ptr = ptr; - return; - } - (*ctx->bctx)->mac(ctx->bctx, - ctx->cbcmac, ctx->buf, sizeof ctx->buf); - } - - /* - * Process all complete blocks. Note that the ctrcbc API is for - * encrypt-then-MAC (CBC-MAC is computed over the encrypted - * blocks) while CCM uses MAC-and-encrypt (CBC-MAC is computed - * over the plaintext blocks). Therefore, we need to use the - * _decryption_ function for encryption, and the encryption - * function for decryption (this works because CTR encryption - * and decryption are identical, so the choice really is about - * computing the CBC-MAC before or after XORing with the CTR - * stream). - */ - ptr = len & 15; - len -= ptr; - if (encrypt) { - (*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, - dbuf, len); - } else { - (*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, - dbuf, len); - } - dbuf += len; - - /* - * If there is some remaining data, then we need to compute an - * extra block of CTR stream. - */ - if (ptr != 0) { - size_t u; - - memset(ctx->buf, 0, sizeof ctx->buf); - (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, - ctx->buf, sizeof ctx->buf); - if (encrypt) { - for (u = 0; u < ptr; u ++) { - unsigned w, x; - - w = ctx->buf[u]; - x = dbuf[u]; - ctx->buf[u] = x; - dbuf[u] = w ^ x; - } - } else { - for (u = 0; u < ptr; u ++) { - unsigned w; - - w = ctx->buf[u] ^ dbuf[u]; - dbuf[u] = w; - ctx->buf[u] = w; - } - } - } - ctx->ptr = ptr; -} - -/* see bearssl_block.h */ -size_t -br_ccm_get_tag(br_ccm_context *ctx, void *tag) -{ - size_t ptr; - size_t u; - - /* - * If there is some buffered data, then we need to pad it with - * zeros and finish up CBC-MAC. - */ - ptr = ctx->ptr; - if (ptr != 0) { - memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr); - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, - ctx->buf, sizeof ctx->buf); - } - - /* - * XOR the tag mask into the CBC-MAC output. - */ - for (u = 0; u < ctx->tag_len; u ++) { - ctx->cbcmac[u] ^= ctx->tagmask[u]; - } - memcpy(tag, ctx->cbcmac, ctx->tag_len); - return ctx->tag_len; -} - -/* see bearssl_block.h */ -uint32_t -br_ccm_check_tag(br_ccm_context *ctx, const void *tag) -{ - unsigned char tmp[16]; - size_t u, tag_len; - uint32_t z; - - tag_len = br_ccm_get_tag(ctx, tmp); - z = 0; - for (u = 0; u < tag_len; u ++) { - z |= tmp[u] ^ ((const unsigned char *)tag)[u]; - } - return EQ0(z); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ccopy.c b/src/tls/bearssl/ccopy.c deleted file mode 100644 index 1c8d6e000..000000000 --- a/src/tls/bearssl/ccopy.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len) -{ - unsigned char *d; - const unsigned char *s; - - d = dst; - s = src; - while (len -- > 0) { - uint32_t x, y; - - x = *s ++; - y = *d; - *d = MUX(ctl, x, y); - d ++; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/chacha20_ct.c b/src/tls/bearssl/chacha20_ct.c deleted file mode 100644 index 503015a13..000000000 --- a/src/tls/bearssl/chacha20_ct.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -uint32_t -br_chacha20_ct_run(const void *key, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - uint32_t kw[8], ivw[3]; - size_t u; - - static const uint32_t CW[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - - buf = data; - for (u = 0; u < 8; u ++) { - kw[u] = br_dec32le((const unsigned char *)key + (u << 2)); - } - for (u = 0; u < 3; u ++) { - ivw[u] = br_dec32le((const unsigned char *)iv + (u << 2)); - } - while (len > 0) { - uint32_t state[16]; - int i; - size_t clen; - unsigned char tmp[64]; - - memcpy(&state[0], CW, sizeof CW); - memcpy(&state[4], kw, sizeof kw); - state[12] = cc; - memcpy(&state[13], ivw, sizeof ivw); - for (i = 0; i < 10; i ++) { - -#define QROUND(a, b, c, d) do { \ - state[a] += state[b]; \ - state[d] ^= state[a]; \ - state[d] = (state[d] << 16) | (state[d] >> 16); \ - state[c] += state[d]; \ - state[b] ^= state[c]; \ - state[b] = (state[b] << 12) | (state[b] >> 20); \ - state[a] += state[b]; \ - state[d] ^= state[a]; \ - state[d] = (state[d] << 8) | (state[d] >> 24); \ - state[c] += state[d]; \ - state[b] ^= state[c]; \ - state[b] = (state[b] << 7) | (state[b] >> 25); \ - } while (0) - - QROUND( 0, 4, 8, 12); - QROUND( 1, 5, 9, 13); - QROUND( 2, 6, 10, 14); - QROUND( 3, 7, 11, 15); - QROUND( 0, 5, 10, 15); - QROUND( 1, 6, 11, 12); - QROUND( 2, 7, 8, 13); - QROUND( 3, 4, 9, 14); - -#undef QROUND - - } - for (u = 0; u < 4; u ++) { - br_enc32le(&tmp[u << 2], state[u] + CW[u]); - } - for (u = 4; u < 12; u ++) { - br_enc32le(&tmp[u << 2], state[u] + kw[u - 4]); - } - br_enc32le(&tmp[48], state[12] + cc); - for (u = 13; u < 16; u ++) { - br_enc32le(&tmp[u << 2], state[u] + ivw[u - 13]); - } - - clen = len < 64 ? len : 64; - for (u = 0; u < clen; u ++) { - buf[u] ^= tmp[u]; - } - buf += clen; - len -= clen; - cc ++; - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/chacha20_sse2.c b/src/tls/bearssl/chacha20_sse2.c deleted file mode 100644 index 6e717d028..000000000 --- a/src/tls/bearssl/chacha20_sse2.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_ENABLE_INTRINSICS 1 -#include "inner.h" - -#if BR_SSE2 - -/* - * This file contains a ChaCha20 implementation that leverages SSE2 - * opcodes for better performance. - */ - -/* see bearssl_block.h */ -br_chacha20_run -br_chacha20_sse2_get(void) -{ - /* - * If using 64-bit mode, then SSE2 opcodes should be automatically - * available, since they are part of the ABI. - * - * In 32-bit mode, we use CPUID to detect the SSE2 feature. - */ - -#if BR_amd64 - return &br_chacha20_sse2_run; -#else - - /* - * SSE2 support is indicated by bit 26 in EDX. - */ - if (br_cpuid(0, 0, 0, 0x04000000)) { - return &br_chacha20_sse2_run; - } else { - return 0; - } -#endif -} - -BR_TARGETS_X86_UP - -/* see bearssl_block.h */ -BR_TARGET("sse2") -uint32_t -br_chacha20_sse2_run(const void *key, - const void *iv, uint32_t cc, void *data, size_t len) -{ - unsigned char *buf; - uint32_t ivtmp[4]; - __m128i kw0, kw1; - __m128i iw, cw; - __m128i one; - - static const uint32_t CW[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - - buf = data; - kw0 = _mm_loadu_si128(key); - kw1 = _mm_loadu_si128((const void *)((const unsigned char *)key + 16)); - ivtmp[0] = cc; - memcpy(ivtmp + 1, iv, 12); - iw = _mm_loadu_si128((const void *)ivtmp); - cw = _mm_loadu_si128((const void *)CW); - one = _mm_set_epi32(0, 0, 0, 1); - - while (len > 0) { - /* - * sj contains state words 4*j to 4*j+3. - */ - __m128i s0, s1, s2, s3; - int i; - - s0 = cw; - s1 = kw0; - s2 = kw1; - s3 = iw; - for (i = 0; i < 10; i ++) { - /* - * Even round is straightforward application on - * the state words. - */ - s0 = _mm_add_epi32(s0, s1); - s3 = _mm_xor_si128(s3, s0); - s3 = _mm_or_si128( - _mm_slli_epi32(s3, 16), - _mm_srli_epi32(s3, 16)); - - s2 = _mm_add_epi32(s2, s3); - s1 = _mm_xor_si128(s1, s2); - s1 = _mm_or_si128( - _mm_slli_epi32(s1, 12), - _mm_srli_epi32(s1, 20)); - - s0 = _mm_add_epi32(s0, s1); - s3 = _mm_xor_si128(s3, s0); - s3 = _mm_or_si128( - _mm_slli_epi32(s3, 8), - _mm_srli_epi32(s3, 24)); - - s2 = _mm_add_epi32(s2, s3); - s1 = _mm_xor_si128(s1, s2); - s1 = _mm_or_si128( - _mm_slli_epi32(s1, 7), - _mm_srli_epi32(s1, 25)); - - /* - * For the odd round, we must rotate some state - * words so that the computations apply on the - * right combinations of words. - */ - s1 = _mm_shuffle_epi32(s1, 0x39); - s2 = _mm_shuffle_epi32(s2, 0x4E); - s3 = _mm_shuffle_epi32(s3, 0x93); - - s0 = _mm_add_epi32(s0, s1); - s3 = _mm_xor_si128(s3, s0); - s3 = _mm_or_si128( - _mm_slli_epi32(s3, 16), - _mm_srli_epi32(s3, 16)); - - s2 = _mm_add_epi32(s2, s3); - s1 = _mm_xor_si128(s1, s2); - s1 = _mm_or_si128( - _mm_slli_epi32(s1, 12), - _mm_srli_epi32(s1, 20)); - - s0 = _mm_add_epi32(s0, s1); - s3 = _mm_xor_si128(s3, s0); - s3 = _mm_or_si128( - _mm_slli_epi32(s3, 8), - _mm_srli_epi32(s3, 24)); - - s2 = _mm_add_epi32(s2, s3); - s1 = _mm_xor_si128(s1, s2); - s1 = _mm_or_si128( - _mm_slli_epi32(s1, 7), - _mm_srli_epi32(s1, 25)); - - /* - * After the odd round, we rotate back the values - * to undo the rotate at the start of the odd round. - */ - s1 = _mm_shuffle_epi32(s1, 0x93); - s2 = _mm_shuffle_epi32(s2, 0x4E); - s3 = _mm_shuffle_epi32(s3, 0x39); - } - - /* - * Addition with the initial state. - */ - s0 = _mm_add_epi32(s0, cw); - s1 = _mm_add_epi32(s1, kw0); - s2 = _mm_add_epi32(s2, kw1); - s3 = _mm_add_epi32(s3, iw); - - /* - * Increment block counter. - */ - iw = _mm_add_epi32(iw, one); - - /* - * XOR final state with the data. - */ - if (len < 64) { - unsigned char tmp[64]; - size_t u; - - _mm_storeu_si128((void *)(tmp + 0), s0); - _mm_storeu_si128((void *)(tmp + 16), s1); - _mm_storeu_si128((void *)(tmp + 32), s2); - _mm_storeu_si128((void *)(tmp + 48), s3); - for (u = 0; u < len; u ++) { - buf[u] ^= tmp[u]; - } - break; - } else { - __m128i b0, b1, b2, b3; - - b0 = _mm_loadu_si128((const void *)(buf + 0)); - b1 = _mm_loadu_si128((const void *)(buf + 16)); - b2 = _mm_loadu_si128((const void *)(buf + 32)); - b3 = _mm_loadu_si128((const void *)(buf + 48)); - b0 = _mm_xor_si128(b0, s0); - b1 = _mm_xor_si128(b1, s1); - b2 = _mm_xor_si128(b2, s2); - b3 = _mm_xor_si128(b3, s3); - _mm_storeu_si128((void *)(buf + 0), b0); - _mm_storeu_si128((void *)(buf + 16), b1); - _mm_storeu_si128((void *)(buf + 32), b2); - _mm_storeu_si128((void *)(buf + 48), b3); - buf += 64; - len -= 64; - } - } - - /* - * _mm_extract_epi32() requires SSE4.1. We prefer to stick to - * raw SSE2, thus we use _mm_extract_epi16(). - */ - return (uint32_t)_mm_extract_epi16(iw, 0) - | ((uint32_t)_mm_extract_epi16(iw, 1) << 16); -} - -BR_TARGETS_X86_DOWN - -#else - -/* see bearssl_block.h */ -br_chacha20_run -br_chacha20_sse2_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/config.h b/src/tls/bearssl/config.h deleted file mode 100644 index 158e6cbe2..000000000 --- a/src/tls/bearssl/config.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CONFIG_H__ -#define CONFIG_H__ - -/* - * This file contains compile-time flags that can override the - * autodetection performed in relevant files. Each flag is a macro; it - * deactivates the feature if defined to 0, activates it if defined to a - * non-zero integer (normally 1). If the macro is not defined, then - * autodetection applies. - */ - -/* - * When BR_64 is enabled, 64-bit integer types are assumed to be - * efficient (i.e. the architecture has 64-bit registers and can - * do 64-bit operations as fast as 32-bit operations). - * -#define BR_64 1 - */ - -/* - * When BR_LOMUL is enabled, then multiplications of 32-bit values whose - * result are truncated to the low 32 bits are assumed to be - * substantially more efficient than 32-bit multiplications that yield - * 64-bit results. This is typically the case on low-end ARM Cortex M - * systems (M0, M0+, M1, and arguably M3 and M4 as well). - * -#define BR_LOMUL 1 - */ -#ifdef ARDUINO -#define BR_LOMUL 1 -#endif - -/* - * When BR_SLOW_MUL is enabled, multiplications are assumed to be - * substantially slow with regards to other integer operations, thus - * making it worth to make more operations for a given task if it allows - * using less multiplications. - * -#define BR_SLOW_MUL 1 - */ - -/* - * When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words) - * are assumed to be substantially slow with regards to other integer - * operations, thus making it worth to make more integer operations if - * it allows using less multiplications. - * -#define BR_SLOW_MUL15 1 - */ - -/* - * When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used - * in the "i31" big integer implementation) use an alternate implementation - * which is slower and larger than the normal multiplication, but should - * ensure constant-time multiplications even on architectures where the - * multiplication opcode takes a variable number of cycles to complete. - * -#define BR_CT_MUL31 1 - */ - -/* - * When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held - * in 32-bit words) use an alternate implementation which is slower and - * larger than the normal multiplication, but should ensure - * constant-time multiplications on most/all architectures where the - * basic multiplication is not constant-time. -#define BR_CT_MUL15 1 - */ - -/* - * When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign - * extension) are performed with a sequence of operations which is bigger - * and slower than a simple right shift on a signed value. This avoids - * relying on an implementation-defined behaviour. However, most if not - * all C compilers use sign extension for right shifts on signed values, - * so this alternate macro is disabled by default. -#define BR_NO_ARITH_SHIFT 1 - */ - -/* - * When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode - * to automatically obtain quality randomness for seeding its internal - * PRNG. Since that opcode is present only in recent x86 CPU, its - * support is dynamically tested; if the current CPU does not support - * it, then another random source will be used, such as /dev/urandom or - * CryptGenRandom(). - * -#define BR_RDRAND 1 - */ - -/* - * When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom - * to automatically obtain quality randomness for seedings its internal - * PRNG. - * -#define BR_USE_URANDOM 1 - */ - -/* - * When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32 - * (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to - * automatically obtain quality randomness for seedings its internal PRNG. - * - * Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the - * former takes precedence. - * -#define BR_USE_WIN32_RAND 1 - */ - -/* - * When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains - * the current time from the OS by calling time(), and assuming that the - * returned value (a 'time_t') is an integer that counts time in seconds - * since the Unix Epoch (Jan 1st, 1970, 00:00 UTC). - * -#define BR_USE_UNIX_TIME 1 - */ - -/* - * When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains - * the current time from the OS by calling the Win32 function - * GetSystemTimeAsFileTime(). - * - * Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the - * former takes precedence. - * -#define BR_USE_WIN32_TIME 1 - */ - -/* - * When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with - * inline assembly which is shorter and/or faster. This should be used - * only when all of the following are true: - * - target architecture is ARM in Thumb mode - * - target endianness is little-endian - * - compiler is GCC (or GCC-compatible for inline assembly syntax) - * - * This is meant for the low-end cores (Cortex M0, M0+, M1, M3). - * Note: if BR_LOMUL is not explicitly enabled or disabled, then - * enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL. - * -#define BR_ARMEL_CORTEXM_GCC 1 - */ -#if defined(ARDUINO) && defined(__arm__) -#define BR_ARMEL_CORTEXM_GCC 1 -#endif - -/* - * When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI" - * instructions (dedicated AES opcodes) will be compiled. If this is not - * enabled explicitly, then that AES implementation will be compiled only - * if a compatible compiler is detected. If set explicitly to 0, the - * implementation will not be compiled at all. - * -#define BR_AES_X86NI 1 - */ - -/* - * When BR_SSE2 is enabled, SSE2 intrinsics will be used for some - * algorithm implementations that use them (e.g. chacha20_sse2). If this - * is not enabled explicitly, then support for SSE2 intrinsics will be - * automatically detected. If set explicitly to 0, then SSE2 code will - * not be compiled at all. - * -#define BR_SSE2 1 - */ - -/* - * When BR_POWER8 is enabled, the AES implementation using the POWER ISA - * 2.07 opcodes (available on POWER8 processors and later) is compiled. - * If this is not enabled explicitly, then that implementation will be - * compiled only if a compatible compiler is detected, _and_ the target - * architecture is POWER8 or later. - * -#define BR_POWER8 1 - */ - -/* - * When BR_INT128 is enabled, then code using the 'unsigned __int64' - * and 'unsigned __int128' types will be used to leverage 64x64->128 - * unsigned multiplications. This should work with GCC and compatible - * compilers on 64-bit architectures. - * -#define BR_INT128 1 - */ - -/* - * When BR_UMUL128 is enabled, then code using the '_umul128()' and - * '_addcarry_u64()' intrinsics will be used to implement 64x64->128 - * unsigned multiplications. This should work on Visual C on x64 systems. - * -#define BR_UMUL128 1 - */ - -/* - * When BR_LE_UNALIGNED is enabled, then the current architecture is - * assumed to use little-endian encoding for integers, and to tolerate - * unaligned accesses with no or minimal time penalty. - * -#define BR_LE_UNALIGNED 1 - */ - -/* - * When BR_BE_UNALIGNED is enabled, then the current architecture is - * assumed to use big-endian encoding for integers, and to tolerate - * unaligned accesses with no or minimal time penalty. - * -#define BR_BE_UNALIGNED 1 - */ - -#endif diff --git a/src/tls/bearssl/dec16be.c b/src/tls/bearssl/dec16be.c deleted file mode 100644 index 4802ffedd..000000000 --- a/src/tls/bearssl/dec16be.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec16be(uint16_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec16be(buf); - buf += 2; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dec16le.c b/src/tls/bearssl/dec16le.c deleted file mode 100644 index 377639a84..000000000 --- a/src/tls/bearssl/dec16le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec16le(uint16_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec16le(buf); - buf += 2; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dec32be.c b/src/tls/bearssl/dec32be.c deleted file mode 100644 index 733381229..000000000 --- a/src/tls/bearssl/dec32be.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ - defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ - defined(ARDUINO_UNOR4_WIFI) - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec32be(uint32_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec32be(buf); - buf += 4; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dec32le.c b/src/tls/bearssl/dec32le.c deleted file mode 100644 index 7fca69ac4..000000000 --- a/src/tls/bearssl/dec32le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec32le(uint32_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec32le(buf); - buf += 4; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dec64be.c b/src/tls/bearssl/dec64be.c deleted file mode 100644 index c0d26628e..000000000 --- a/src/tls/bearssl/dec64be.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec64be(uint64_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec64be(buf); - buf += 8; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dec64le.c b/src/tls/bearssl/dec64le.c deleted file mode 100644 index 293fd2d99..000000000 --- a/src/tls/bearssl/dec64le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_dec64le(uint64_t *v, size_t num, const void *src) -{ - const unsigned char *buf; - - buf = src; - while (num -- > 0) { - *v ++ = br_dec64le(buf); - buf += 8; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_ct.c b/src/tls/bearssl/des_ct.c deleted file mode 100644 index 5b13c97ff..000000000 --- a/src/tls/bearssl/des_ct.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * During key schedule, we need to apply bit extraction PC-2 then permute - * things into our bitslice representation. PC-2 extracts 48 bits out - * of two 28-bit words (kl and kr), and we store these bits into two - * 32-bit words sk0 and sk1. - * - * -- bit 16+x of sk0 comes from bit QL0[x] of kl - * -- bit x of sk0 comes from bit QR0[x] of kr - * -- bit 16+x of sk1 comes from bit QL1[x] of kl - * -- bit x of sk1 comes from bit QR1[x] of kr - */ - -static const unsigned char QL0[] = { - 17, 4, 27, 23, 13, 22, 7, 18, - 16, 24, 2, 20, 1, 8, 15, 26 -}; - -static const unsigned char QR0[] = { - 25, 19, 9, 1, 5, 11, 23, 8, - 17, 0, 22, 3, 6, 20, 27, 24 -}; - -static const unsigned char QL1[] = { - 28, 28, 14, 11, 28, 28, 25, 0, - 28, 28, 5, 9, 28, 28, 12, 21 -}; - -static const unsigned char QR1[] = { - 28, 28, 15, 4, 28, 28, 26, 16, - 28, 28, 12, 7, 28, 28, 10, 14 -}; - -/* - * 32-bit rotation. The C compiler is supposed to recognize it as a - * rotation and use the local architecture rotation opcode (if available). - */ -static inline uint32_t -rotl(uint32_t x, int n) -{ - return (x << n) | (x >> (32 - n)); -} - -/* - * Compute key schedule for 8 key bytes (produces 32 subkey words). - */ -static void -keysched_unit(uint32_t *skey, const void *key) -{ - int i; - - br_des_keysched_unit(skey, key); - - /* - * Apply PC-2 + bitslicing. - */ - for (i = 0; i < 16; i ++) { - uint32_t kl, kr, sk0, sk1; - int j; - - kl = skey[(i << 1) + 0]; - kr = skey[(i << 1) + 1]; - sk0 = 0; - sk1 = 0; - for (j = 0; j < 16; j ++) { - sk0 <<= 1; - sk1 <<= 1; - sk0 |= ((kl >> QL0[j]) & (uint32_t)1) << 16; - sk0 |= (kr >> QR0[j]) & (uint32_t)1; - sk1 |= ((kl >> QL1[j]) & (uint32_t)1) << 16; - sk1 |= (kr >> QR1[j]) & (uint32_t)1; - } - - skey[(i << 1) + 0] = sk0; - skey[(i << 1) + 1] = sk1; - } - -#if 0 - /* - * Speed-optimized version for PC-2 + bitslicing. - * (Unused. Kept for reference only.) - */ - sk0 = kl & (uint32_t)0x00100000; - sk0 |= (kl & (uint32_t)0x08008000) << 2; - sk0 |= (kl & (uint32_t)0x00400000) << 4; - sk0 |= (kl & (uint32_t)0x00800000) << 5; - sk0 |= (kl & (uint32_t)0x00040000) << 6; - sk0 |= (kl & (uint32_t)0x00010000) << 7; - sk0 |= (kl & (uint32_t)0x00000100) << 10; - sk0 |= (kl & (uint32_t)0x00022000) << 14; - sk0 |= (kl & (uint32_t)0x00000082) << 18; - sk0 |= (kl & (uint32_t)0x00000004) << 19; - sk0 |= (kl & (uint32_t)0x04000000) >> 10; - sk0 |= (kl & (uint32_t)0x00000010) << 26; - sk0 |= (kl & (uint32_t)0x01000000) >> 2; - - sk0 |= kr & (uint32_t)0x00000100; - sk0 |= (kr & (uint32_t)0x00000008) << 1; - sk0 |= (kr & (uint32_t)0x00000200) << 4; - sk0 |= rotl(kr & (uint32_t)0x08000021, 6); - sk0 |= (kr & (uint32_t)0x01000000) >> 24; - sk0 |= (kr & (uint32_t)0x00000002) << 11; - sk0 |= (kr & (uint32_t)0x00100000) >> 18; - sk0 |= (kr & (uint32_t)0x00400000) >> 17; - sk0 |= (kr & (uint32_t)0x00800000) >> 14; - sk0 |= (kr & (uint32_t)0x02020000) >> 10; - sk0 |= (kr & (uint32_t)0x00080000) >> 5; - sk0 |= (kr & (uint32_t)0x00000040) >> 3; - sk0 |= (kr & (uint32_t)0x00000800) >> 1; - - sk1 = kl & (uint32_t)0x02000000; - sk1 |= (kl & (uint32_t)0x00001000) << 5; - sk1 |= (kl & (uint32_t)0x00000200) << 11; - sk1 |= (kl & (uint32_t)0x00004000) << 15; - sk1 |= (kl & (uint32_t)0x00000020) << 16; - sk1 |= (kl & (uint32_t)0x00000800) << 17; - sk1 |= (kl & (uint32_t)0x00000001) << 24; - sk1 |= (kl & (uint32_t)0x00200000) >> 5; - - sk1 |= (kr & (uint32_t)0x00000010) << 8; - sk1 |= (kr & (uint32_t)0x04000000) >> 17; - sk1 |= (kr & (uint32_t)0x00004000) >> 14; - sk1 |= (kr & (uint32_t)0x00000400) >> 9; - sk1 |= (kr & (uint32_t)0x00010000) >> 8; - sk1 |= (kr & (uint32_t)0x00001000) >> 7; - sk1 |= (kr & (uint32_t)0x00000080) >> 3; - sk1 |= (kr & (uint32_t)0x00008000) >> 2; -#endif -} - -/* see inner.h */ -unsigned -br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len) -{ - switch (key_len) { - case 8: - keysched_unit(skey, key); - return 1; - case 16: - keysched_unit(skey, key); - keysched_unit(skey + 32, (const unsigned char *)key + 8); - br_des_rev_skey(skey + 32); - memcpy(skey + 64, skey, 32 * sizeof *skey); - return 3; - default: - keysched_unit(skey, key); - keysched_unit(skey + 32, (const unsigned char *)key + 8); - br_des_rev_skey(skey + 32); - keysched_unit(skey + 64, (const unsigned char *)key + 16); - return 3; - } -} - -/* - * DES confusion function. This function performs expansion E (32 to - * 48 bits), XOR with subkey, S-boxes, and permutation P. - */ -static inline uint32_t -Fconf(uint32_t r0, const uint32_t *sk) -{ - /* - * Each 6->4 S-box is virtually turned into four 6->1 boxes; we - * thus end up with 32 boxes that we call "T-boxes" here. We will - * evaluate them with bitslice code. - * - * Each T-box is a circuit of multiplexers (sort of) and thus - * takes 70 inputs: the 6 actual T-box inputs, and 64 constants - * that describe the T-box output for all combinations of the - * 6 inputs. With this model, all T-boxes are identical (with - * distinct inputs) and thus can be executed in parallel with - * bitslice code. - * - * T-boxes are numbered from 0 to 31, in least-to-most - * significant order. Thus, S-box S1 corresponds to T-boxes 31, - * 30, 29 and 28, in that order. T-box 'n' is computed with the - * bits at rank 'n' in the 32-bit words. - * - * Words x0 to x5 contain the T-box inputs 0 to 5. - */ - uint32_t x0, x1, x2, x3, x4, x5, z0; - uint32_t y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; - uint32_t y20, y21, y22, y23, y24, y25, y26, y27, y28, y29; - uint32_t y30; - - /* - * Spread input bits over the 6 input words x*. - */ - x1 = r0 & (uint32_t)0x11111111; - x2 = (r0 >> 1) & (uint32_t)0x11111111; - x3 = (r0 >> 2) & (uint32_t)0x11111111; - x4 = (r0 >> 3) & (uint32_t)0x11111111; - x1 = (x1 << 4) - x1; - x2 = (x2 << 4) - x2; - x3 = (x3 << 4) - x3; - x4 = (x4 << 4) - x4; - x0 = (x4 << 4) | (x4 >> 28); - x5 = (x1 >> 4) | (x1 << 28); - - /* - * XOR with the subkey for this round. - */ - x0 ^= sk[0]; - x1 ^= sk[1]; - x2 ^= sk[2]; - x3 ^= sk[3]; - x4 ^= sk[4]; - x5 ^= sk[5]; - - /* - * The T-boxes are done in parallel, since they all use a - * "tree of multiplexer". We use "fake multiplexers": - * - * y = a ^ (x & b) - * - * computes y as either 'a' (if x == 0) or 'a ^ b' (if x == 1). - */ - y0 = (uint32_t)0xEFA72C4D ^ (x0 & (uint32_t)0xEC7AC69C); - y1 = (uint32_t)0xAEAAEDFF ^ (x0 & (uint32_t)0x500FB821); - y2 = (uint32_t)0x37396665 ^ (x0 & (uint32_t)0x40EFA809); - y3 = (uint32_t)0x68D7B833 ^ (x0 & (uint32_t)0xA5EC0B28); - y4 = (uint32_t)0xC9C755BB ^ (x0 & (uint32_t)0x252CF820); - y5 = (uint32_t)0x73FC3606 ^ (x0 & (uint32_t)0x40205801); - y6 = (uint32_t)0xA2A0A918 ^ (x0 & (uint32_t)0xE220F929); - y7 = (uint32_t)0x8222BD90 ^ (x0 & (uint32_t)0x44A3F9E1); - y8 = (uint32_t)0xD6B6AC77 ^ (x0 & (uint32_t)0x794F104A); - y9 = (uint32_t)0x3069300C ^ (x0 & (uint32_t)0x026F320B); - y10 = (uint32_t)0x6CE0D5CC ^ (x0 & (uint32_t)0x7640B01A); - y11 = (uint32_t)0x59A9A22D ^ (x0 & (uint32_t)0x238F1572); - y12 = (uint32_t)0xAC6D0BD4 ^ (x0 & (uint32_t)0x7A63C083); - y13 = (uint32_t)0x21C83200 ^ (x0 & (uint32_t)0x11CCA000); - y14 = (uint32_t)0xA0E62188 ^ (x0 & (uint32_t)0x202F69AA); - /* y15 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */ - y16 = (uint32_t)0xAF7D655A ^ (x0 & (uint32_t)0x51B33BE9); - y17 = (uint32_t)0xF0168AA3 ^ (x0 & (uint32_t)0x3B0FE8AE); - y18 = (uint32_t)0x90AA30C6 ^ (x0 & (uint32_t)0x90BF8816); - y19 = (uint32_t)0x5AB2750A ^ (x0 & (uint32_t)0x09E34F9B); - y20 = (uint32_t)0x5391BE65 ^ (x0 & (uint32_t)0x0103BE88); - y21 = (uint32_t)0x93372BAF ^ (x0 & (uint32_t)0x49AC8E25); - y22 = (uint32_t)0xF288210C ^ (x0 & (uint32_t)0x922C313D); - y23 = (uint32_t)0x920AF5C0 ^ (x0 & (uint32_t)0x70EF31B0); - y24 = (uint32_t)0x63D312C0 ^ (x0 & (uint32_t)0x6A707100); - y25 = (uint32_t)0x537B3006 ^ (x0 & (uint32_t)0xB97C9011); - y26 = (uint32_t)0xA2EFB0A5 ^ (x0 & (uint32_t)0xA320C959); - y27 = (uint32_t)0xBC8F96A5 ^ (x0 & (uint32_t)0x6EA0AB4A); - y28 = (uint32_t)0xFAD176A5 ^ (x0 & (uint32_t)0x6953DDF8); - y29 = (uint32_t)0x665A14A3 ^ (x0 & (uint32_t)0xF74F3E2B); - y30 = (uint32_t)0xF2EFF0CC ^ (x0 & (uint32_t)0xF0306CAD); - /* y31 = (uint32_t)0x00000000 ^ (x0 & (uint32_t)0x00000000); */ - - y0 = y0 ^ (x1 & y1); - y1 = y2 ^ (x1 & y3); - y2 = y4 ^ (x1 & y5); - y3 = y6 ^ (x1 & y7); - y4 = y8 ^ (x1 & y9); - y5 = y10 ^ (x1 & y11); - y6 = y12 ^ (x1 & y13); - y7 = y14; /* was: y14 ^ (x1 & y15) */ - y8 = y16 ^ (x1 & y17); - y9 = y18 ^ (x1 & y19); - y10 = y20 ^ (x1 & y21); - y11 = y22 ^ (x1 & y23); - y12 = y24 ^ (x1 & y25); - y13 = y26 ^ (x1 & y27); - y14 = y28 ^ (x1 & y29); - y15 = y30; /* was: y30 ^ (x1 & y31) */ - - y0 = y0 ^ (x2 & y1); - y1 = y2 ^ (x2 & y3); - y2 = y4 ^ (x2 & y5); - y3 = y6 ^ (x2 & y7); - y4 = y8 ^ (x2 & y9); - y5 = y10 ^ (x2 & y11); - y6 = y12 ^ (x2 & y13); - y7 = y14 ^ (x2 & y15); - - y0 = y0 ^ (x3 & y1); - y1 = y2 ^ (x3 & y3); - y2 = y4 ^ (x3 & y5); - y3 = y6 ^ (x3 & y7); - - y0 = y0 ^ (x4 & y1); - y1 = y2 ^ (x4 & y3); - - y0 = y0 ^ (x5 & y1); - - /* - * The P permutation: - * -- Each bit move is converted into a mask + left rotation. - * -- Rotations that use the same movement are coalesced together. - * -- Left and right shifts are used as alternatives to a rotation - * where appropriate (this will help architectures that do not have - * a rotation opcode). - */ - z0 = (y0 & (uint32_t)0x00000004) << 3; - z0 |= (y0 & (uint32_t)0x00004000) << 4; - z0 |= rotl(y0 & 0x12020120, 5); - z0 |= (y0 & (uint32_t)0x00100000) << 6; - z0 |= (y0 & (uint32_t)0x00008000) << 9; - z0 |= (y0 & (uint32_t)0x04000000) >> 22; - z0 |= (y0 & (uint32_t)0x00000001) << 11; - z0 |= rotl(y0 & 0x20000200, 12); - z0 |= (y0 & (uint32_t)0x00200000) >> 19; - z0 |= (y0 & (uint32_t)0x00000040) << 14; - z0 |= (y0 & (uint32_t)0x00010000) << 15; - z0 |= (y0 & (uint32_t)0x00000002) << 16; - z0 |= rotl(y0 & 0x40801800, 17); - z0 |= (y0 & (uint32_t)0x00080000) >> 13; - z0 |= (y0 & (uint32_t)0x00000010) << 21; - z0 |= (y0 & (uint32_t)0x01000000) >> 10; - z0 |= rotl(y0 & 0x88000008, 24); - z0 |= (y0 & (uint32_t)0x00000480) >> 7; - z0 |= (y0 & (uint32_t)0x00442000) >> 6; - return z0; -} - -/* - * Process one block through 16 successive rounds, omitting the swap - * in the final round. - */ -static void -process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *sk_exp) -{ - int i; - uint32_t l, r; - - l = *pl; - r = *pr; - for (i = 0; i < 16; i ++) { - uint32_t t; - - t = l ^ Fconf(r, sk_exp); - l = r; - r = t; - sk_exp += 6; - } - *pl = r; - *pr = l; -} - -/* see inner.h */ -void -br_des_ct_process_block(unsigned num_rounds, - const uint32_t *sk_exp, void *block) -{ - unsigned char *buf; - uint32_t l, r; - - buf = block; - l = br_dec32be(buf); - r = br_dec32be(buf + 4); - br_des_do_IP(&l, &r); - while (num_rounds -- > 0) { - process_block_unit(&l, &r, sk_exp); - sk_exp += 96; - } - br_des_do_invIP(&l, &r); - br_enc32be(buf, l); - br_enc32be(buf + 4, r); -} - -/* see inner.h */ -void -br_des_ct_skey_expand(uint32_t *sk_exp, - unsigned num_rounds, const uint32_t *skey) -{ - num_rounds <<= 4; - while (num_rounds -- > 0) { - uint32_t v, w0, w1, w2, w3; - - v = *skey ++; - w0 = v & 0x11111111; - w1 = (v >> 1) & 0x11111111; - w2 = (v >> 2) & 0x11111111; - w3 = (v >> 3) & 0x11111111; - *sk_exp ++ = (w0 << 4) - w0; - *sk_exp ++ = (w1 << 4) - w1; - *sk_exp ++ = (w2 << 4) - w2; - *sk_exp ++ = (w3 << 4) - w3; - v = *skey ++; - w0 = v & 0x11111111; - w1 = (v >> 1) & 0x11111111; - *sk_exp ++ = (w0 << 4) - w0; - *sk_exp ++ = (w1 << 4) - w1; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_ct_cbcdec.c b/src/tls/bearssl/des_ct_cbcdec.c deleted file mode 100644 index b0742ae84..000000000 --- a/src/tls/bearssl/des_ct_cbcdec.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_des_ct_cbcdec_vtable; - ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len); - if (len == 8) { - br_des_rev_skey(ctx->skey); - } else { - int i; - - for (i = 0; i < 48; i += 2) { - uint32_t t; - - t = ctx->skey[i]; - ctx->skey[i] = ctx->skey[94 - i]; - ctx->skey[94 - i] = t; - t = ctx->skey[i + 1]; - ctx->skey[i + 1] = ctx->skey[95 - i]; - ctx->skey[95 - i] = t; - } - } -} - -/* see bearssl_block.h */ -void -br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - uint32_t sk_exp[288]; - - br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - ivbuf = iv; - buf = data; - while (len > 0) { - unsigned char tmp[8]; - int i; - - memcpy(tmp, buf, 8); - br_des_ct_process_block(ctx->num_rounds, sk_exp, buf); - for (i = 0; i < 8; i ++) { - buf[i] ^= ivbuf[i]; - } - memcpy(ivbuf, tmp, 8); - buf += 8; - len -= 8; - } -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_des_ct_cbcdec_vtable = { - sizeof(br_des_ct_cbcdec_keys), - 8, - 3, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_des_ct_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_des_ct_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_ct_cbcenc.c b/src/tls/bearssl/des_ct_cbcenc.c deleted file mode 100644 index aa60b4ff5..000000000 --- a/src/tls/bearssl/des_ct_cbcenc.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_des_ct_cbcenc_vtable; - ctx->num_rounds = br_des_ct_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - uint32_t sk_exp[288]; - - br_des_ct_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); - ivbuf = iv; - buf = data; - while (len > 0) { - int i; - - for (i = 0; i < 8; i ++) { - buf[i] ^= ivbuf[i]; - } - br_des_ct_process_block(ctx->num_rounds, sk_exp, buf); - memcpy(ivbuf, buf, 8); - buf += 8; - len -= 8; - } -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_des_ct_cbcenc_vtable = { - sizeof(br_des_ct_cbcenc_keys), - 8, - 3, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_des_ct_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_des_ct_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_support.c b/src/tls/bearssl/des_support.c deleted file mode 100644 index 4db9bd87e..000000000 --- a/src/tls/bearssl/des_support.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_des_do_IP(uint32_t *xl, uint32_t *xr) -{ - /* - * Permutation algorithm is initially from Richard Outerbridge; - * implementation here is adapted from Crypto++ "des.cpp" file - * (which is in public domain). - */ - uint32_t l, r, t; - - l = *xl; - r = *xr; - t = ((l >> 4) ^ r) & (uint32_t)0x0F0F0F0F; - r ^= t; - l ^= t << 4; - t = ((l >> 16) ^ r) & (uint32_t)0x0000FFFF; - r ^= t; - l ^= t << 16; - t = ((r >> 2) ^ l) & (uint32_t)0x33333333; - l ^= t; - r ^= t << 2; - t = ((r >> 8) ^ l) & (uint32_t)0x00FF00FF; - l ^= t; - r ^= t << 8; - t = ((l >> 1) ^ r) & (uint32_t)0x55555555; - r ^= t; - l ^= t << 1; - *xl = l; - *xr = r; -} - -/* see inner.h */ -void -br_des_do_invIP(uint32_t *xl, uint32_t *xr) -{ - /* - * See br_des_do_IP(). - */ - uint32_t l, r, t; - - l = *xl; - r = *xr; - t = ((l >> 1) ^ r) & 0x55555555; - r ^= t; - l ^= t << 1; - t = ((r >> 8) ^ l) & 0x00FF00FF; - l ^= t; - r ^= t << 8; - t = ((r >> 2) ^ l) & 0x33333333; - l ^= t; - r ^= t << 2; - t = ((l >> 16) ^ r) & 0x0000FFFF; - r ^= t; - l ^= t << 16; - t = ((l >> 4) ^ r) & 0x0F0F0F0F; - r ^= t; - l ^= t << 4; - *xl = l; - *xr = r; -} - -/* see inner.h */ -void -br_des_keysched_unit(uint32_t *skey, const void *key) -{ - uint32_t xl, xr, kl, kr; - int i; - - xl = br_dec32be(key); - xr = br_dec32be((const unsigned char *)key + 4); - - /* - * Permutation PC-1 is quite similar to the IP permutation. - * Definition of IP (in FIPS 46-3 notations) is: - * 58 50 42 34 26 18 10 2 - * 60 52 44 36 28 20 12 4 - * 62 54 46 38 30 22 14 6 - * 64 56 48 40 32 24 16 8 - * 57 49 41 33 25 17 9 1 - * 59 51 43 35 27 19 11 3 - * 61 53 45 37 29 21 13 5 - * 63 55 47 39 31 23 15 7 - * - * Definition of PC-1 is: - * 57 49 41 33 25 17 9 1 - * 58 50 42 34 26 18 10 2 - * 59 51 43 35 27 19 11 3 - * 60 52 44 36 - * 63 55 47 39 31 23 15 7 - * 62 54 46 38 30 22 14 6 - * 61 53 45 37 29 21 13 5 - * 28 20 12 4 - */ - br_des_do_IP(&xl, &xr); - kl = ((xr & (uint32_t)0xFF000000) >> 4) - | ((xl & (uint32_t)0xFF000000) >> 12) - | ((xr & (uint32_t)0x00FF0000) >> 12) - | ((xl & (uint32_t)0x00FF0000) >> 20); - kr = ((xr & (uint32_t)0x000000FF) << 20) - | ((xl & (uint32_t)0x0000FF00) << 4) - | ((xr & (uint32_t)0x0000FF00) >> 4) - | ((xl & (uint32_t)0x000F0000) >> 16); - - /* - * For each round, rotate the two 28-bit words kl and kr. - * The extraction of the 48-bit subkey (PC-2) is not done yet. - */ - for (i = 0; i < 16; i ++) { - if ((1 << i) & 0x8103) { - kl = (kl << 1) | (kl >> 27); - kr = (kr << 1) | (kr >> 27); - } else { - kl = (kl << 2) | (kl >> 26); - kr = (kr << 2) | (kr >> 26); - } - kl &= (uint32_t)0x0FFFFFFF; - kr &= (uint32_t)0x0FFFFFFF; - skey[(i << 1) + 0] = kl; - skey[(i << 1) + 1] = kr; - } -} - -/* see inner.h */ -void -br_des_rev_skey(uint32_t *skey) -{ - int i; - - for (i = 0; i < 16; i += 2) { - uint32_t t; - - t = skey[i + 0]; - skey[i + 0] = skey[30 - i]; - skey[30 - i] = t; - t = skey[i + 1]; - skey[i + 1] = skey[31 - i]; - skey[31 - i] = t; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_tab.c b/src/tls/bearssl/des_tab.c deleted file mode 100644 index dd6063ece..000000000 --- a/src/tls/bearssl/des_tab.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * PC2left[x] tells where bit x goes when applying PC-2. 'x' is a bit - * position in the left rotated key word. Both position are in normal - * order (rightmost bit is 0). - */ -static const unsigned char PC2left[] = { - 16, 3, 7, 24, 20, 11, 24, - 13, 2, 10, 24, 22, 5, 15, - 23, 1, 9, 21, 12, 24, 6, - 4, 14, 18, 8, 17, 0, 19 -}; - -/* - * Similar to PC2left[x], for the right rotated key word. - */ -static const unsigned char PC2right[] = { - 8, 18, 24, 6, 22, 15, 3, - 10, 12, 19, 5, 14, 11, 24, - 4, 23, 16, 9, 24, 20, 2, - 24, 7, 13, 0, 21, 17, 1 -}; - -/* - * S-boxes and PC-1 merged. - */ -static const uint32_t S1[] = { - 0x00808200, 0x00000000, 0x00008000, 0x00808202, - 0x00808002, 0x00008202, 0x00000002, 0x00008000, - 0x00000200, 0x00808200, 0x00808202, 0x00000200, - 0x00800202, 0x00808002, 0x00800000, 0x00000002, - 0x00000202, 0x00800200, 0x00800200, 0x00008200, - 0x00008200, 0x00808000, 0x00808000, 0x00800202, - 0x00008002, 0x00800002, 0x00800002, 0x00008002, - 0x00000000, 0x00000202, 0x00008202, 0x00800000, - 0x00008000, 0x00808202, 0x00000002, 0x00808000, - 0x00808200, 0x00800000, 0x00800000, 0x00000200, - 0x00808002, 0x00008000, 0x00008200, 0x00800002, - 0x00000200, 0x00000002, 0x00800202, 0x00008202, - 0x00808202, 0x00008002, 0x00808000, 0x00800202, - 0x00800002, 0x00000202, 0x00008202, 0x00808200, - 0x00000202, 0x00800200, 0x00800200, 0x00000000, - 0x00008002, 0x00008200, 0x00000000, 0x00808002 -}; - -static const uint32_t S2[] = { - 0x40084010, 0x40004000, 0x00004000, 0x00084010, - 0x00080000, 0x00000010, 0x40080010, 0x40004010, - 0x40000010, 0x40084010, 0x40084000, 0x40000000, - 0x40004000, 0x00080000, 0x00000010, 0x40080010, - 0x00084000, 0x00080010, 0x40004010, 0x00000000, - 0x40000000, 0x00004000, 0x00084010, 0x40080000, - 0x00080010, 0x40000010, 0x00000000, 0x00084000, - 0x00004010, 0x40084000, 0x40080000, 0x00004010, - 0x00000000, 0x00084010, 0x40080010, 0x00080000, - 0x40004010, 0x40080000, 0x40084000, 0x00004000, - 0x40080000, 0x40004000, 0x00000010, 0x40084010, - 0x00084010, 0x00000010, 0x00004000, 0x40000000, - 0x00004010, 0x40084000, 0x00080000, 0x40000010, - 0x00080010, 0x40004010, 0x40000010, 0x00080010, - 0x00084000, 0x00000000, 0x40004000, 0x00004010, - 0x40000000, 0x40080010, 0x40084010, 0x00084000 -}; - -static const uint32_t S3[] = { - 0x00000104, 0x04010100, 0x00000000, 0x04010004, - 0x04000100, 0x00000000, 0x00010104, 0x04000100, - 0x00010004, 0x04000004, 0x04000004, 0x00010000, - 0x04010104, 0x00010004, 0x04010000, 0x00000104, - 0x04000000, 0x00000004, 0x04010100, 0x00000100, - 0x00010100, 0x04010000, 0x04010004, 0x00010104, - 0x04000104, 0x00010100, 0x00010000, 0x04000104, - 0x00000004, 0x04010104, 0x00000100, 0x04000000, - 0x04010100, 0x04000000, 0x00010004, 0x00000104, - 0x00010000, 0x04010100, 0x04000100, 0x00000000, - 0x00000100, 0x00010004, 0x04010104, 0x04000100, - 0x04000004, 0x00000100, 0x00000000, 0x04010004, - 0x04000104, 0x00010000, 0x04000000, 0x04010104, - 0x00000004, 0x00010104, 0x00010100, 0x04000004, - 0x04010000, 0x04000104, 0x00000104, 0x04010000, - 0x00010104, 0x00000004, 0x04010004, 0x00010100 -}; - -static const uint32_t S4[] = { - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x00401040, 0x80400040, 0x80400000, 0x80001000, - 0x00000000, 0x00401000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00400040, 0x80400000, - 0x80000000, 0x00001000, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x80001000, 0x00001040, - 0x80400040, 0x80000000, 0x00001040, 0x00400040, - 0x00001000, 0x00401040, 0x80401040, 0x80000040, - 0x00400040, 0x80400000, 0x00401000, 0x80401040, - 0x80000040, 0x00000000, 0x00000000, 0x00401000, - 0x00001040, 0x00400040, 0x80400040, 0x80000000, - 0x80401000, 0x80001040, 0x80001040, 0x00000040, - 0x80401040, 0x80000040, 0x80000000, 0x00001000, - 0x80400000, 0x80001000, 0x00401040, 0x80400040, - 0x80001000, 0x00001040, 0x00400000, 0x80401000, - 0x00000040, 0x00400000, 0x00001000, 0x00401040 -}; - -static const uint32_t S5[] = { - 0x00000080, 0x01040080, 0x01040000, 0x21000080, - 0x00040000, 0x00000080, 0x20000000, 0x01040000, - 0x20040080, 0x00040000, 0x01000080, 0x20040080, - 0x21000080, 0x21040000, 0x00040080, 0x20000000, - 0x01000000, 0x20040000, 0x20040000, 0x00000000, - 0x20000080, 0x21040080, 0x21040080, 0x01000080, - 0x21040000, 0x20000080, 0x00000000, 0x21000000, - 0x01040080, 0x01000000, 0x21000000, 0x00040080, - 0x00040000, 0x21000080, 0x00000080, 0x01000000, - 0x20000000, 0x01040000, 0x21000080, 0x20040080, - 0x01000080, 0x20000000, 0x21040000, 0x01040080, - 0x20040080, 0x00000080, 0x01000000, 0x21040000, - 0x21040080, 0x00040080, 0x21000000, 0x21040080, - 0x01040000, 0x00000000, 0x20040000, 0x21000000, - 0x00040080, 0x01000080, 0x20000080, 0x00040000, - 0x00000000, 0x20040000, 0x01040080, 0x20000080 -}; - -static const uint32_t S6[] = { - 0x10000008, 0x10200000, 0x00002000, 0x10202008, - 0x10200000, 0x00000008, 0x10202008, 0x00200000, - 0x10002000, 0x00202008, 0x00200000, 0x10000008, - 0x00200008, 0x10002000, 0x10000000, 0x00002008, - 0x00000000, 0x00200008, 0x10002008, 0x00002000, - 0x00202000, 0x10002008, 0x00000008, 0x10200008, - 0x10200008, 0x00000000, 0x00202008, 0x10202000, - 0x00002008, 0x00202000, 0x10202000, 0x10000000, - 0x10002000, 0x00000008, 0x10200008, 0x00202000, - 0x10202008, 0x00200000, 0x00002008, 0x10000008, - 0x00200000, 0x10002000, 0x10000000, 0x00002008, - 0x10000008, 0x10202008, 0x00202000, 0x10200000, - 0x00202008, 0x10202000, 0x00000000, 0x10200008, - 0x00000008, 0x00002000, 0x10200000, 0x00202008, - 0x00002000, 0x00200008, 0x10002008, 0x00000000, - 0x10202000, 0x10000000, 0x00200008, 0x10002008 -}; - -static const uint32_t S7[] = { - 0x00100000, 0x02100001, 0x02000401, 0x00000000, - 0x00000400, 0x02000401, 0x00100401, 0x02100400, - 0x02100401, 0x00100000, 0x00000000, 0x02000001, - 0x00000001, 0x02000000, 0x02100001, 0x00000401, - 0x02000400, 0x00100401, 0x00100001, 0x02000400, - 0x02000001, 0x02100000, 0x02100400, 0x00100001, - 0x02100000, 0x00000400, 0x00000401, 0x02100401, - 0x00100400, 0x00000001, 0x02000000, 0x00100400, - 0x02000000, 0x00100400, 0x00100000, 0x02000401, - 0x02000401, 0x02100001, 0x02100001, 0x00000001, - 0x00100001, 0x02000000, 0x02000400, 0x00100000, - 0x02100400, 0x00000401, 0x00100401, 0x02100400, - 0x00000401, 0x02000001, 0x02100401, 0x02100000, - 0x00100400, 0x00000000, 0x00000001, 0x02100401, - 0x00000000, 0x00100401, 0x02100000, 0x00000400, - 0x02000001, 0x02000400, 0x00000400, 0x00100001 -}; - -static const uint32_t S8[] = { - 0x08000820, 0x00000800, 0x00020000, 0x08020820, - 0x08000000, 0x08000820, 0x00000020, 0x08000000, - 0x00020020, 0x08020000, 0x08020820, 0x00020800, - 0x08020800, 0x00020820, 0x00000800, 0x00000020, - 0x08020000, 0x08000020, 0x08000800, 0x00000820, - 0x00020800, 0x00020020, 0x08020020, 0x08020800, - 0x00000820, 0x00000000, 0x00000000, 0x08020020, - 0x08000020, 0x08000800, 0x00020820, 0x00020000, - 0x00020820, 0x00020000, 0x08020800, 0x00000800, - 0x00000020, 0x08020020, 0x00000800, 0x00020820, - 0x08000800, 0x00000020, 0x08000020, 0x08020000, - 0x08020020, 0x08000000, 0x00020000, 0x08000820, - 0x00000000, 0x08020820, 0x00020020, 0x08000020, - 0x08020000, 0x08000800, 0x08000820, 0x00000000, - 0x08020820, 0x00020800, 0x00020800, 0x00000820, - 0x00000820, 0x00020020, 0x08000000, 0x08020800 -}; - -static inline uint32_t -Fconf(uint32_t r0, uint32_t skl, uint32_t skr) -{ - uint32_t r1; - - r1 = (r0 << 16) | (r0 >> 16); - return - S1[((r1 >> 11) ^ (skl >> 18)) & 0x3F] - | S2[((r0 >> 23) ^ (skl >> 12)) & 0x3F] - | S3[((r0 >> 19) ^ (skl >> 6)) & 0x3F] - | S4[((r0 >> 15) ^ (skl )) & 0x3F] - | S5[((r0 >> 11) ^ (skr >> 18)) & 0x3F] - | S6[((r0 >> 7) ^ (skr >> 12)) & 0x3F] - | S7[((r0 >> 3) ^ (skr >> 6)) & 0x3F] - | S8[((r1 >> 15) ^ (skr )) & 0x3F]; -} - -static void -process_block_unit(uint32_t *pl, uint32_t *pr, const uint32_t *skey) -{ - int i; - uint32_t l, r; - - l = *pl; - r = *pr; - for (i = 0; i < 16; i ++) { - uint32_t t; - - t = l ^ Fconf(r, skey[(i << 1) + 0], skey[(i << 1) + 1]); - l = r; - r = t; - } - *pl = r; - *pr = l; -} - -/* see inner.h */ -void -br_des_tab_process_block(unsigned num_rounds, const uint32_t *skey, void *block) -{ - unsigned char *buf; - uint32_t l, r; - - buf = block; - l = br_dec32be(buf); - r = br_dec32be(buf + 4); - br_des_do_IP(&l, &r); - while (num_rounds -- > 0) { - process_block_unit(&l, &r, skey); - skey += 32; - } - br_des_do_invIP(&l, &r); - br_enc32be(buf, l); - br_enc32be(buf + 4, r); -} - -static void -keysched_unit(uint32_t *skey, const void *key) -{ - int i; - - br_des_keysched_unit(skey, key); - - /* - * Apply PC-2 to get the 48-bit subkeys. - */ - for (i = 0; i < 16; i ++) { - uint32_t xl, xr, ul, ur; - int j; - - xl = skey[(i << 1) + 0]; - xr = skey[(i << 1) + 1]; - ul = 0; - ur = 0; - for (j = 0; j < 28; j ++) { - ul |= (xl & 1) << PC2left[j]; - ur |= (xr & 1) << PC2right[j]; - xl >>= 1; - xr >>= 1; - } - skey[(i << 1) + 0] = ul; - skey[(i << 1) + 1] = ur; - } -} - -/* see inner.h */ -unsigned -br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len) -{ - switch (key_len) { - case 8: - keysched_unit(skey, key); - return 1; - case 16: - keysched_unit(skey, key); - keysched_unit(skey + 32, (const unsigned char *)key + 8); - br_des_rev_skey(skey + 32); - memcpy(skey + 64, skey, 32 * sizeof *skey); - return 3; - default: - keysched_unit(skey, key); - keysched_unit(skey + 32, (const unsigned char *)key + 8); - br_des_rev_skey(skey + 32); - keysched_unit(skey + 64, (const unsigned char *)key + 16); - return 3; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_tab_cbcdec.c b/src/tls/bearssl/des_tab_cbcdec.c deleted file mode 100644 index f7d3e3064..000000000 --- a/src/tls/bearssl/des_tab_cbcdec.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_des_tab_cbcdec_vtable; - ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len); - if (len == 8) { - br_des_rev_skey(ctx->skey); - } else { - int i; - - for (i = 0; i < 48; i += 2) { - uint32_t t; - - t = ctx->skey[i]; - ctx->skey[i] = ctx->skey[94 - i]; - ctx->skey[94 - i] = t; - t = ctx->skey[i + 1]; - ctx->skey[i + 1] = ctx->skey[95 - i]; - ctx->skey[95 - i] = t; - } - } -} - -/* see bearssl_block.h */ -void -br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - unsigned char tmp[8]; - int i; - - memcpy(tmp, buf, 8); - br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf); - for (i = 0; i < 8; i ++) { - buf[i] ^= ivbuf[i]; - } - memcpy(ivbuf, tmp, 8); - buf += 8; - len -= 8; - } -} - -/* see bearssl_block.h */ -const br_block_cbcdec_class br_des_tab_cbcdec_vtable = { - sizeof(br_des_tab_cbcdec_keys), - 8, - 3, - (void (*)(const br_block_cbcdec_class **, const void *, size_t)) - &br_des_tab_cbcdec_init, - (void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t)) - &br_des_tab_cbcdec_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/des_tab_cbcenc.c b/src/tls/bearssl/des_tab_cbcenc.c deleted file mode 100644 index e1a3359c2..000000000 --- a/src/tls/bearssl/des_tab_cbcenc.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_block.h */ -void -br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx, - const void *key, size_t len) -{ - ctx->vtable = &br_des_tab_cbcenc_vtable; - ctx->num_rounds = br_des_tab_keysched(ctx->skey, key, len); -} - -/* see bearssl_block.h */ -void -br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, - void *iv, void *data, size_t len) -{ - unsigned char *buf, *ivbuf; - - ivbuf = iv; - buf = data; - while (len > 0) { - int i; - - for (i = 0; i < 8; i ++) { - buf[i] ^= ivbuf[i]; - } - br_des_tab_process_block(ctx->num_rounds, ctx->skey, buf); - memcpy(ivbuf, buf, 8); - buf += 8; - len -= 8; - } -} - -/* see bearssl_block.h */ -const br_block_cbcenc_class br_des_tab_cbcenc_vtable = { - sizeof(br_des_tab_cbcenc_keys), - 8, - 3, - (void (*)(const br_block_cbcenc_class **, const void *, size_t)) - &br_des_tab_cbcenc_init, - (void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t)) - &br_des_tab_cbcenc_run -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dig_oid.c b/src/tls/bearssl/dig_oid.c deleted file mode 100644 index 85be00106..000000000 --- a/src/tls/bearssl/dig_oid.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * This file contains the encoded OID for the standard hash functions. - * Such OID appear in, for instance, the PKCS#1 v1.5 padding for RSA - * signatures. - */ - -static const unsigned char md5_OID[] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05 -}; - -static const unsigned char sha1_OID[] = { - 0x2B, 0x0E, 0x03, 0x02, 0x1A -}; - -static const unsigned char sha224_OID[] = { - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 -}; - -static const unsigned char sha256_OID[] = { - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 -}; - -static const unsigned char sha384_OID[] = { - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 -}; - -static const unsigned char sha512_OID[] = { - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 -}; - -/* see inner.h */ -const unsigned char * -br_digest_OID(int digest_id, size_t *len) -{ - switch (digest_id) { - case br_md5_ID: - *len = sizeof md5_OID; - return md5_OID; - case br_sha1_ID: - *len = sizeof sha1_OID; - return sha1_OID; - case br_sha224_ID: - *len = sizeof sha224_OID; - return sha224_OID; - case br_sha256_ID: - *len = sizeof sha256_OID; - return sha256_OID; - case br_sha384_ID: - *len = sizeof sha384_OID; - return sha384_OID; - case br_sha512_ID: - *len = sizeof sha512_OID; - return sha512_OID; - default: - *len = 0; - return NULL; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/dig_size.c b/src/tls/bearssl/dig_size.c deleted file mode 100644 index 40de304a2..000000000 --- a/src/tls/bearssl/dig_size.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -size_t -br_digest_size_by_ID(int digest_id) -{ - switch (digest_id) { - case br_md5sha1_ID: - return br_md5_SIZE + br_sha1_SIZE; - case br_md5_ID: - return br_md5_SIZE; - case br_sha1_ID: - return br_sha1_SIZE; - case br_sha224_ID: - return br_sha224_SIZE; - case br_sha256_ID: - return br_sha256_SIZE; - case br_sha384_ID: - return br_sha384_SIZE; - case br_sha512_ID: - return br_sha512_SIZE; - default: - /* abort(); */ - return 0; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/eax.c b/src/tls/bearssl/eax.c deleted file mode 100644 index fcd20012d..000000000 --- a/src/tls/bearssl/eax.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Implementation Notes - * ==================== - * - * The combined CTR + CBC-MAC functions can only handle full blocks, - * so some buffering is necessary. Moreover, EAX has a special padding - * rule for CBC-MAC, which implies that we cannot compute the MAC over - * the last received full block until we know whether we are at the - * end of the data or not. - * - * - 'ptr' contains a value from 1 to 16, which is the number of bytes - * accumulated in buf[] that still needs to be processed with the - * current OMAC computation. Beware that this can go to 16: a - * complete block cannot be processed until it is known whether it - * is the last block or not. However, it can never be 0, because - * OMAC^t works on an input that is at least one-block long. - * - * - When processing the message itself, CTR encryption/decryption is - * also done at the same time. The first 'ptr' bytes of buf[] then - * contains the encrypted bytes, while the last '16 - ptr' bytes of - * buf[] are the remnants of the stream block, to be used against - * the next input bytes, when available. - * - * - The current counter and running CBC-MAC values are kept in 'ctr' - * and 'cbcmac', respectively. - * - * - The derived keys for padding are kept in L2 and L4 (double and - * quadruple of Enc_K(0^n), in GF(2^128), respectively). - */ - -/* - * Start an OMAC computation; the first block is the big-endian - * representation of the provided value ('val' must fit on one byte). - * We make it a delayed block because it may also be the last one, - */ -static void -omac_start(br_eax_context *ctx, unsigned val) -{ - memset(ctx->cbcmac, 0, sizeof ctx->cbcmac); - memset(ctx->buf, 0, sizeof ctx->buf); - ctx->buf[15] = val; - ctx->ptr = 16; -} - -/* - * Double a value in finite field GF(2^128), defined with modulus - * X^128+X^7+X^2+X+1. - */ -static void -double_gf128(unsigned char *dst, const unsigned char *src) -{ - unsigned cc; - int i; - - cc = 0x87 & -((unsigned)src[0] >> 7); - for (i = 15; i >= 0; i --) { - unsigned z; - - z = (src[i] << 1) ^ cc; - cc = z >> 8; - dst[i] = (unsigned char)z; - } -} - -/* - * Apply padding to the last block, currently in ctx->buf (with - * ctx->ptr bytes), and finalize OMAC computation. - */ -static void -do_pad(br_eax_context *ctx) -{ - unsigned char *pad; - size_t ptr, u; - - ptr = ctx->ptr; - if (ptr == 16) { - pad = ctx->L2; - } else { - ctx->buf[ptr ++] = 0x80; - memset(ctx->buf + ptr, 0x00, 16 - ptr); - pad = ctx->L4; - } - for (u = 0; u < sizeof ctx->buf; u ++) { - ctx->buf[u] ^= pad[u]; - } - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf); -} - -/* - * Apply CBC-MAC on the provided data, with buffering management. - * - * Upon entry, two situations are acceptable: - * - * ctx->ptr == 0: there is no data to process in ctx->buf - * ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf - * - * Upon exit, ctx->ptr may be zero only if it was already zero on entry, - * and len == 0. In all other situations, ctx->ptr will be non-zero on - * exit (and may have value 16). - */ -static void -do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len) -{ - size_t ptr; - - if (len == 0) { - return; - } - ptr = len & (size_t)15; - if (ptr == 0) { - len -= 16; - ptr = 16; - } else { - len -= ptr; - } - if (ctx->ptr == 16) { - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, - ctx->buf, sizeof ctx->buf); - } - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len); - memcpy(ctx->buf, (const unsigned char *)data + len, ptr); - ctx->ptr = ptr; -} - -/* see bearssl_aead.h */ -void -br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx) -{ - unsigned char tmp[16], iv[16]; - - ctx->vtable = &br_eax_vtable; - ctx->bctx = bctx; - - /* - * Encrypt a whole-zero block to compute L2 and L4. - */ - memset(tmp, 0, sizeof tmp); - memset(iv, 0, sizeof iv); - (*bctx)->ctr(bctx, iv, tmp, sizeof tmp); - double_gf128(ctx->L2, tmp); - double_gf128(ctx->L4, ctx->L2); -} - -/* see bearssl_aead.h */ -void -br_eax_capture(const br_eax_context *ctx, br_eax_state *st) -{ - /* - * We capture the three OMAC* states _after_ processing the - * initial block (assuming that nonce, message and AAD are - * all non-empty). - */ - int i; - - memset(st->st, 0, sizeof st->st); - for (i = 0; i < 3; i ++) { - unsigned char tmp[16]; - - memset(tmp, 0, sizeof tmp); - tmp[15] = (unsigned char)i; - (*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp); - } -} - -/* see bearssl_aead.h */ -void -br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len) -{ - /* - * Process nonce with OMAC^0. - */ - omac_start(ctx, 0); - do_cbcmac_chunk(ctx, nonce, len); - do_pad(ctx); - memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); - - /* - * Start OMAC^1 for the AAD ("header" in the EAX specification). - */ - omac_start(ctx, 1); - - /* - * We use ctx->head[0] as temporary flag to mark that we are - * using a "normal" reset(). - */ - ctx->head[0] = 0; -} - -/* see bearssl_aead.h */ -void -br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st, - const void *nonce, size_t len) -{ - if (len == 0) { - omac_start(ctx, 0); - } else { - memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac); - ctx->ptr = 0; - do_cbcmac_chunk(ctx, nonce, len); - } - do_pad(ctx); - memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); - - memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac); - ctx->ptr = 0; - - memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr); - - /* - * We use ctx->head[0] as a flag to indicate that we use a - * a recorded state, with ctx->ctr containing the preprocessed - * first block for OMAC^2. - */ - ctx->head[0] = 1; -} - -/* see bearssl_aead.h */ -void -br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st, - const void *nonce, size_t len) -{ - if (len == 0) { - omac_start(ctx, 0); - } else { - memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac); - ctx->ptr = 0; - do_cbcmac_chunk(ctx, nonce, len); - } - do_pad(ctx); - memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac); - memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce); - - memcpy(ctx->head, st->st[1], sizeof ctx->head); - - memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac); - ctx->ptr = 0; -} - -/* see bearssl_aead.h */ -void -br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len) -{ - size_t ptr; - - ptr = ctx->ptr; - - /* - * If there is a partial block, first complete it. - */ - if (ptr < 16) { - size_t clen; - - clen = 16 - ptr; - if (len <= clen) { - memcpy(ctx->buf + ptr, data, len); - ctx->ptr = ptr + len; - return; - } - memcpy(ctx->buf + ptr, data, clen); - data = (const unsigned char *)data + clen; - len -= clen; - } - - /* - * We now have a full block in buf[], and this is not the last - * block. - */ - do_cbcmac_chunk(ctx, data, len); -} - -/* see bearssl_aead.h */ -void -br_eax_flip(br_eax_context *ctx) -{ - int from_capture; - - /* - * ctx->head[0] may be non-zero if the context was reset with - * a pre-AAD captured state. In that case, ctx->ctr[] contains - * the state for OMAC^2 _after_ processing the first block. - */ - from_capture = ctx->head[0]; - - /* - * Complete the OMAC computation on the AAD. - */ - do_pad(ctx); - memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac); - - /* - * Start OMAC^2 for the encrypted data. - * If the context was initialized from a captured state, then - * the OMAC^2 value is in the ctr[] array. - */ - if (from_capture) { - memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac); - ctx->ptr = 0; - } else { - omac_start(ctx, 2); - } - - /* - * Initial counter value for CTR is the processed nonce. - */ - memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce); -} - -/* see bearssl_aead.h */ -void -br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len) -{ - unsigned char *dbuf; - size_t ptr; - - /* - * Ensure that there is actual data to process. - */ - if (len == 0) { - return; - } - - dbuf = data; - ptr = ctx->ptr; - - /* - * We may have ptr == 0 here if we initialized from a captured - * state. In that case, there is no partially consumed block - * or unprocessed data. - */ - if (ptr != 0 && ptr != 16) { - /* - * We have a partially consumed block. - */ - size_t u, clen; - - clen = 16 - ptr; - if (len <= clen) { - clen = len; - } - if (encrypt) { - for (u = 0; u < clen; u ++) { - ctx->buf[ptr + u] ^= dbuf[u]; - } - memcpy(dbuf, ctx->buf + ptr, clen); - } else { - for (u = 0; u < clen; u ++) { - unsigned dx, sx; - - sx = ctx->buf[ptr + u]; - dx = dbuf[u]; - ctx->buf[ptr + u] = dx; - dbuf[u] = sx ^ dx; - } - } - - if (len <= clen) { - ctx->ptr = ptr + clen; - return; - } - dbuf += clen; - len -= clen; - } - - /* - * We now have a complete encrypted block in buf[] that must still - * be processed with OMAC, and this is not the final buf. - * Exception: when ptr == 0, no block has been produced yet. - */ - if (ptr != 0) { - (*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, - ctx->buf, sizeof ctx->buf); - } - - /* - * Do CTR encryption or decryption and CBC-MAC for all full blocks - * except the last. - */ - ptr = len & (size_t)15; - if (ptr == 0) { - len -= 16; - ptr = 16; - } else { - len -= ptr; - } - if (encrypt) { - (*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, - dbuf, len); - } else { - (*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac, - dbuf, len); - } - dbuf += len; - - /* - * Compute next block of CTR stream, and use it to finish - * encrypting or decrypting the data. - */ - memset(ctx->buf, 0, sizeof ctx->buf); - (*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf); - if (encrypt) { - size_t u; - - for (u = 0; u < ptr; u ++) { - ctx->buf[u] ^= dbuf[u]; - } - memcpy(dbuf, ctx->buf, ptr); - } else { - size_t u; - - for (u = 0; u < ptr; u ++) { - unsigned dx, sx; - - sx = ctx->buf[u]; - dx = dbuf[u]; - ctx->buf[u] = dx; - dbuf[u] = sx ^ dx; - } - } - ctx->ptr = ptr; -} - -/* - * Complete tag computation. The final tag is written in ctx->cbcmac. - */ -static void -do_final(br_eax_context *ctx) -{ - size_t u; - - do_pad(ctx); - - /* - * Authentication tag is the XOR of the three OMAC outputs for - * the nonce, AAD and encrypted data. - */ - for (u = 0; u < 16; u ++) { - ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u]; - } -} - -/* see bearssl_aead.h */ -void -br_eax_get_tag(br_eax_context *ctx, void *tag) -{ - do_final(ctx); - memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac); -} - -/* see bearssl_aead.h */ -void -br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len) -{ - do_final(ctx); - memcpy(tag, ctx->cbcmac, len); -} - -/* see bearssl_aead.h */ -uint32_t -br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len) -{ - unsigned char tmp[16]; - size_t u; - int x; - - br_eax_get_tag(ctx, tmp); - x = 0; - for (u = 0; u < len; u ++) { - x |= tmp[u] ^ ((const unsigned char *)tag)[u]; - } - return EQ0(x); -} - -/* see bearssl_aead.h */ -uint32_t -br_eax_check_tag(br_eax_context *ctx, const void *tag) -{ - return br_eax_check_tag_trunc(ctx, tag, 16); -} - -/* see bearssl_aead.h */ -const br_aead_class br_eax_vtable = { - 16, - (void (*)(const br_aead_class **, const void *, size_t)) - &br_eax_reset, - (void (*)(const br_aead_class **, const void *, size_t)) - &br_eax_aad_inject, - (void (*)(const br_aead_class **)) - &br_eax_flip, - (void (*)(const br_aead_class **, int, void *, size_t)) - &br_eax_run, - (void (*)(const br_aead_class **, void *)) - &br_eax_get_tag, - (uint32_t (*)(const br_aead_class **, const void *)) - &br_eax_check_tag, - (void (*)(const br_aead_class **, void *, size_t)) - &br_eax_get_tag_trunc, - (uint32_t (*)(const br_aead_class **, const void *, size_t)) - &br_eax_check_tag_trunc -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_all_m15.c b/src/tls/bearssl/ec_all_m15.c deleted file mode 100644 index dea4e6b0d..000000000 --- a/src/tls/bearssl/ec_all_m15.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.generator(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m15.generator(curve, len); - default: - return br_ec_prime_i15.generator(curve, len); - } -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.order(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m15.order(curve, len); - default: - return br_ec_prime_i15.order(curve, len); - } -} - -static size_t -api_xoff(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.xoff(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m15.xoff(curve, len); - default: - return br_ec_prime_i15.xoff(curve, len); - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve); - default: - return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve); - } -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.mulgen(R, x, xlen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m15.mulgen(R, x, xlen, curve); - default: - return br_ec_prime_i15.mulgen(R, x, xlen, curve); - } -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m15.muladd(A, B, len, - x, xlen, y, ylen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m15.muladd(A, B, len, - x, xlen, y, ylen, curve); - default: - return br_ec_prime_i15.muladd(A, B, len, - x, xlen, y, ylen, curve); - } -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_all_m15 = { - (uint32_t)0x23800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_all_m31.c b/src/tls/bearssl/ec_all_m31.c deleted file mode 100644 index 66168c27d..000000000 --- a/src/tls/bearssl/ec_all_m31.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.generator(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m31.generator(curve, len); - default: - return br_ec_prime_i31.generator(curve, len); - } -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.order(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m31.order(curve, len); - default: - return br_ec_prime_i31.order(curve, len); - } -} - -static size_t -api_xoff(int curve, size_t *len) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.xoff(curve, len); - case BR_EC_curve25519: - return br_ec_c25519_m31.xoff(curve, len); - default: - return br_ec_prime_i31.xoff(curve, len); - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.mul(G, Glen, kb, kblen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m31.mul(G, Glen, kb, kblen, curve); - default: - return br_ec_prime_i31.mul(G, Glen, kb, kblen, curve); - } -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.mulgen(R, x, xlen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m31.mulgen(R, x, xlen, curve); - default: - return br_ec_prime_i31.mulgen(R, x, xlen, curve); - } -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return br_ec_p256_m31.muladd(A, B, len, - x, xlen, y, ylen, curve); - case BR_EC_curve25519: - return br_ec_c25519_m31.muladd(A, B, len, - x, xlen, y, ylen, curve); - default: - return br_ec_prime_i31.muladd(A, B, len, - x, xlen, y, ylen, curve); - } -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_all_m31 = { - (uint32_t)0x23800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_c25519_i15.c b/src/tls/bearssl/ec_c25519_i15.c deleted file mode 100644 index 68ca1fda6..000000000 --- a/src/tls/bearssl/ec_c25519_i15.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Parameters for the field: - * - field modulus p = 2^255-19 - * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p) - */ - -static const uint16_t C255_P[] = { - 0x0110, - 0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF -}; - -#define P0I 0x4A1B - -static const uint16_t C255_R2[] = { - 0x0110, - 0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000 -}; - -/* obsolete -#include -#include -static void -print_int_mont(const char *name, const uint16_t *x) -{ - uint16_t y[18]; - unsigned char tmp[32]; - size_t u; - - printf("%s = ", name); - memcpy(y, x, sizeof y); - br_i15_from_monty(y, C255_P, P0I); - br_i15_encode(tmp, sizeof tmp, y); - for (u = 0; u < sizeof tmp; u ++) { - printf("%02X", tmp[u]); - } - printf("\n"); -} -*/ - -static const uint16_t C255_A24[] = { - 0x0110, - 0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000 -}; - -static const unsigned char GEN[] = { - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char ORDER[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return GEN; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return ORDER; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 0; -} - -static void -cswap(uint16_t *a, uint16_t *b, uint32_t ctl) -{ - int i; - - ctl = -ctl; - for (i = 0; i < 18; i ++) { - uint32_t aw, bw, tw; - - aw = a[i]; - bw = b[i]; - tw = ctl & (aw ^ bw); - a[i] = aw ^ tw; - b[i] = bw ^ tw; - } -} - -static void -c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b) -{ - uint32_t ctl; - uint16_t t[18]; - - memcpy(t, a, sizeof t); - ctl = br_i15_add(t, b, 1); - ctl |= NOT(br_i15_sub(t, C255_P, 0)); - br_i15_sub(t, C255_P, ctl); - memcpy(d, t, sizeof t); -} - -static void -c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b) -{ - uint16_t t[18]; - - memcpy(t, a, sizeof t); - br_i15_add(t, C255_P, br_i15_sub(t, b, 1)); - memcpy(d, t, sizeof t); -} - -static void -c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b) -{ - uint16_t t[18]; - - br_i15_montymul(t, a, b, C255_P, P0I); - memcpy(d, t, sizeof t); -} - -static void -byteswap(unsigned char *G) -{ - int i; - - for (i = 0; i < 16; i ++) { - unsigned char t; - - t = G[i]; - G[i] = G[31 - i]; - G[31 - i] = t; - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ -#define ILEN (18 * sizeof(uint16_t)) - - /* - * The a[] and b[] arrays have an extra word to allow for - * decoding without using br_i15_decode_reduce(). - */ - uint16_t x1[18], x2[18], x3[18], z2[18], z3[18]; - uint16_t a[19], aa[18], b[19], bb[18]; - uint16_t c[18], d[18], e[18], da[18], cb[18]; - unsigned char k[32]; - uint32_t swap; - int i; - - (void)curve; - - /* - * Points are encoded over exactly 32 bytes. Multipliers must fit - * in 32 bytes as well. - * RFC 7748 mandates that the high bit of the last point byte must - * be ignored/cleared. - */ - if (Glen != 32 || kblen > 32) { - return 0; - } - G[31] &= 0x7F; - - /* - * Byteswap the point encoding, because it uses little-endian, and - * the generic decoding routine uses big-endian. - */ - byteswap(G); - - /* - * Decode the point ('u' coordinate). This should be reduced - * modulo p, but we prefer to avoid the dependency on - * br_i15_decode_reduce(). Instead, we use br_i15_decode_mod() - * with a synthetic modulus of value 2^255 (this must work - * since G was truncated to 255 bits), then use a conditional - * subtraction. We use br_i15_decode_mod() and not - * br_i15_decode(), because the ec_prime_i15 implementation uses - * the former but not the latter. - * br_i15_decode_reduce(a, G, 32, C255_P); - */ - br_i15_zero(b, 0x111); - b[18] = 1; - br_i15_decode_mod(a, G, 32, b); - a[0] = 0x110; - br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0))); - - /* - * Initialise variables x1, x2, z2, x3 and z3. We set all of them - * into Montgomery representation. - */ - br_i15_montymul(x1, a, C255_R2, C255_P, P0I); - memcpy(x3, x1, ILEN); - br_i15_zero(z2, C255_P[0]); - memcpy(x2, z2, ILEN); - x2[1] = 19; - memcpy(z3, x2, ILEN); - - memcpy(k, kb, kblen); - memset(k + kblen, 0, (sizeof k) - kblen); - k[0] &= 0xF8; - k[31] &= 0x7F; - k[31] |= 0x40; - - /* obsolete - print_int_mont("x1", x1); - */ - - swap = 0; - for (i = 254; i >= 0; i --) { - uint32_t kt; - - kt = (k[i >> 3] >> (i & 7)) & 1; - swap ^= kt; - cswap(x2, x3, swap); - cswap(z2, z3, swap); - swap = kt; - - /* obsolete - print_int_mont("x2", x2); - print_int_mont("z2", z2); - print_int_mont("x3", x3); - print_int_mont("z3", z3); - */ - - c255_add(a, x2, z2); - c255_mul(aa, a, a); - c255_sub(b, x2, z2); - c255_mul(bb, b, b); - c255_sub(e, aa, bb); - c255_add(c, x3, z3); - c255_sub(d, x3, z3); - c255_mul(da, d, a); - c255_mul(cb, c, b); - - /* obsolete - print_int_mont("a ", a); - print_int_mont("aa", aa); - print_int_mont("b ", b); - print_int_mont("bb", bb); - print_int_mont("e ", e); - print_int_mont("c ", c); - print_int_mont("d ", d); - print_int_mont("da", da); - print_int_mont("cb", cb); - */ - - c255_add(x3, da, cb); - c255_mul(x3, x3, x3); - c255_sub(z3, da, cb); - c255_mul(z3, z3, z3); - c255_mul(z3, z3, x1); - c255_mul(x2, aa, bb); - c255_mul(z2, C255_A24, e); - c255_add(z2, z2, aa); - c255_mul(z2, e, z2); - - /* obsolete - print_int_mont("x2", x2); - print_int_mont("z2", z2); - print_int_mont("x3", x3); - print_int_mont("z3", z3); - */ - } - cswap(x2, x3, swap); - cswap(z2, z3, swap); - - /* - * Inverse z2 with a modular exponentiation. This is a simple - * square-and-multiply algorithm; we mutualise most non-squarings - * since the exponent contains almost only ones. - */ - memcpy(a, z2, ILEN); - for (i = 0; i < 15; i ++) { - c255_mul(a, a, a); - c255_mul(a, a, z2); - } - memcpy(b, a, ILEN); - for (i = 0; i < 14; i ++) { - int j; - - for (j = 0; j < 16; j ++) { - c255_mul(b, b, b); - } - c255_mul(b, b, a); - } - for (i = 14; i >= 0; i --) { - c255_mul(b, b, b); - if ((0xFFEB >> i) & 1) { - c255_mul(b, z2, b); - } - } - c255_mul(b, x2, b); - - /* - * To avoid a dependency on br_i15_from_monty(), we use a - * Montgomery multiplication with 1. - * memcpy(x2, b, ILEN); - * br_i15_from_monty(x2, C255_P, P0I); - */ - br_i15_zero(a, C255_P[0]); - a[1] = 1; - br_i15_montymul(x2, a, b, C255_P, P0I); - - br_i15_encode(G, 32, x2); - byteswap(G); - return 1; - -#undef ILEN -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - /* - * We don't implement this method, since it is used for ECDSA - * only, and there is no ECDSA over Curve25519 (which instead - * uses EdDSA). - */ - (void)A; - (void)B; - (void)len; - (void)x; - (void)xlen; - (void)y; - (void)ylen; - (void)curve; - return 0; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_c25519_i15 = { - (uint32_t)0x20000000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_c25519_i31.c b/src/tls/bearssl/ec_c25519_i31.c deleted file mode 100644 index 47451d38a..000000000 --- a/src/tls/bearssl/ec_c25519_i31.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Parameters for the field: - * - field modulus p = 2^255-19 - * - R^2 mod p (R = 2^(31k) for the smallest k such that R >= p) - */ - -static const uint32_t C255_P[] = { - 0x00000107, - 0x7FFFFFED, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0000007F -}; - -#define P0I 0x286BCA1B - -static const uint32_t C255_R2[] = { - 0x00000107, - 0x00000000, 0x02D20000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 -}; - -static const uint32_t C255_A24[] = { - 0x00000107, - 0x53000000, 0x0000468B, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000 -}; - -/* obsolete -#include -#include -static void -print_int_mont(const char *name, const uint32_t *x) -{ - uint32_t y[10]; - unsigned char tmp[32]; - size_t u; - - printf("%s = ", name); - memcpy(y, x, sizeof y); - br_i31_from_monty(y, C255_P, P0I); - br_i31_encode(tmp, sizeof tmp, y); - for (u = 0; u < sizeof tmp; u ++) { - printf("%02X", tmp[u]); - } - printf("\n"); -} -*/ - -static const unsigned char GEN[] = { - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char ORDER[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return GEN; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return ORDER; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 0; -} - -static void -cswap(uint32_t *a, uint32_t *b, uint32_t ctl) -{ - int i; - - ctl = -ctl; - for (i = 0; i < 10; i ++) { - uint32_t aw, bw, tw; - - aw = a[i]; - bw = b[i]; - tw = ctl & (aw ^ bw); - a[i] = aw ^ tw; - b[i] = bw ^ tw; - } -} - -static void -c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t ctl; - uint32_t t[10]; - - memcpy(t, a, sizeof t); - ctl = br_i31_add(t, b, 1); - ctl |= NOT(br_i31_sub(t, C255_P, 0)); - br_i31_sub(t, C255_P, ctl); - memcpy(d, t, sizeof t); -} - -static void -c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[10]; - - memcpy(t, a, sizeof t); - br_i31_add(t, C255_P, br_i31_sub(t, b, 1)); - memcpy(d, t, sizeof t); -} - -static void -c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[10]; - - br_i31_montymul(t, a, b, C255_P, P0I); - memcpy(d, t, sizeof t); -} - -static void -byteswap(unsigned char *G) -{ - int i; - - for (i = 0; i < 16; i ++) { - unsigned char t; - - t = G[i]; - G[i] = G[31 - i]; - G[31 - i] = t; - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ - uint32_t x1[10], x2[10], x3[10], z2[10], z3[10]; - uint32_t a[10], aa[10], b[10], bb[10]; - uint32_t c[10], d[10], e[10], da[10], cb[10]; - unsigned char k[32]; - uint32_t swap; - int i; - - (void)curve; - - /* - * Points are encoded over exactly 32 bytes. Multipliers must fit - * in 32 bytes as well. - * RFC 7748 mandates that the high bit of the last point byte must - * be ignored/cleared. - */ - if (Glen != 32 || kblen > 32) { - return 0; - } - G[31] &= 0x7F; - - /* - * Byteswap the point encoding, because it uses little-endian, and - * the generic decoding routine uses big-endian. - */ - byteswap(G); - - /* - * Decode the point ('u' coordinate). This should be reduced - * modulo p, but we prefer to avoid the dependency on - * br_i31_decode_reduce(). Instead, we use br_i31_decode_mod() - * with a synthetic modulus of value 2^255 (this must work - * since G was truncated to 255 bits), then use a conditional - * subtraction. We use br_i31_decode_mod() and not - * br_i31_decode(), because the ec_prime_i31 implementation uses - * the former but not the latter. - * br_i31_decode_reduce(a, G, 32, C255_P); - */ - br_i31_zero(b, 0x108); - b[9] = 0x0100; - br_i31_decode_mod(a, G, 32, b); - a[0] = 0x107; - br_i31_sub(a, C255_P, NOT(br_i31_sub(a, C255_P, 0))); - - /* - * Initialise variables x1, x2, z2, x3 and z3. We set all of them - * into Montgomery representation. - */ - br_i31_montymul(x1, a, C255_R2, C255_P, P0I); - memcpy(x3, x1, sizeof x1); - br_i31_zero(z2, C255_P[0]); - memcpy(x2, z2, sizeof z2); - x2[1] = 0x13000000; - memcpy(z3, x2, sizeof x2); - - memcpy(k, kb, kblen); - memset(k + kblen, 0, (sizeof k) - kblen); - k[0] &= 0xF8; - k[31] &= 0x7F; - k[31] |= 0x40; - - /* obsolete - print_int_mont("x1", x1); - */ - - swap = 0; - for (i = 254; i >= 0; i --) { - uint32_t kt; - - kt = (k[i >> 3] >> (i & 7)) & 1; - swap ^= kt; - cswap(x2, x3, swap); - cswap(z2, z3, swap); - swap = kt; - - /* obsolete - print_int_mont("x2", x2); - print_int_mont("z2", z2); - print_int_mont("x3", x3); - print_int_mont("z3", z3); - */ - - c255_add(a, x2, z2); - c255_mul(aa, a, a); - c255_sub(b, x2, z2); - c255_mul(bb, b, b); - c255_sub(e, aa, bb); - c255_add(c, x3, z3); - c255_sub(d, x3, z3); - c255_mul(da, d, a); - c255_mul(cb, c, b); - - /* obsolete - print_int_mont("a ", a); - print_int_mont("aa", aa); - print_int_mont("b ", b); - print_int_mont("bb", bb); - print_int_mont("e ", e); - print_int_mont("c ", c); - print_int_mont("d ", d); - print_int_mont("da", da); - print_int_mont("cb", cb); - */ - - c255_add(x3, da, cb); - c255_mul(x3, x3, x3); - c255_sub(z3, da, cb); - c255_mul(z3, z3, z3); - c255_mul(z3, z3, x1); - c255_mul(x2, aa, bb); - c255_mul(z2, C255_A24, e); - c255_add(z2, z2, aa); - c255_mul(z2, e, z2); - - /* obsolete - print_int_mont("x2", x2); - print_int_mont("z2", z2); - print_int_mont("x3", x3); - print_int_mont("z3", z3); - */ - } - cswap(x2, x3, swap); - cswap(z2, z3, swap); - - /* - * Inverse z2 with a modular exponentiation. This is a simple - * square-and-multiply algorithm; we mutualise most non-squarings - * since the exponent contains almost only ones. - */ - memcpy(a, z2, sizeof z2); - for (i = 0; i < 15; i ++) { - c255_mul(a, a, a); - c255_mul(a, a, z2); - } - memcpy(b, a, sizeof a); - for (i = 0; i < 14; i ++) { - int j; - - for (j = 0; j < 16; j ++) { - c255_mul(b, b, b); - } - c255_mul(b, b, a); - } - for (i = 14; i >= 0; i --) { - c255_mul(b, b, b); - if ((0xFFEB >> i) & 1) { - c255_mul(b, z2, b); - } - } - c255_mul(b, x2, b); - - /* - * To avoid a dependency on br_i31_from_monty(), we use - * a Montgomery multiplication with 1. - * memcpy(x2, b, sizeof b); - * br_i31_from_monty(x2, C255_P, P0I); - */ - br_i31_zero(a, C255_P[0]); - a[1] = 1; - br_i31_montymul(x2, a, b, C255_P, P0I); - - br_i31_encode(G, 32, x2); - byteswap(G); - return 1; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - /* - * We don't implement this method, since it is used for ECDSA - * only, and there is no ECDSA over Curve25519 (which instead - * uses EdDSA). - */ - (void)A; - (void)B; - (void)len; - (void)x; - (void)xlen; - (void)y; - (void)ylen; - (void)curve; - return 0; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_c25519_i31 = { - (uint32_t)0x20000000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_c25519_m15.c b/src/tls/bearssl/ec_c25519_m15.c deleted file mode 100644 index 3b0deff44..000000000 --- a/src/tls/bearssl/ec_c25519_m15.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* obsolete -#include -#include -static void -print_int(const char *name, const uint32_t *x) -{ - size_t u; - unsigned char tmp[36]; - - printf("%s = ", name); - for (u = 0; u < 20; u ++) { - if (x[u] > 0x1FFF) { - printf("INVALID:"); - for (u = 0; u < 20; u ++) { - printf(" %04X", x[u]); - } - printf("\n"); - return; - } - } - memset(tmp, 0, sizeof tmp); - for (u = 0; u < 20; u ++) { - uint32_t w; - int j, k; - - w = x[u]; - j = 13 * (int)u; - k = j & 7; - if (k != 0) { - w <<= k; - j -= k; - } - k = j >> 3; - tmp[35 - k] |= (unsigned char)w; - tmp[34 - k] |= (unsigned char)(w >> 8); - tmp[33 - k] |= (unsigned char)(w >> 16); - tmp[32 - k] |= (unsigned char)(w >> 24); - } - for (u = 4; u < 36; u ++) { - printf("%02X", tmp[u]); - } - printf("\n"); -} -*/ - -/* - * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ - * that right-shifting a signed negative integer copies the sign bit - * (arithmetic right-shift). This is "implementation-defined behaviour", - * i.e. it is not undefined, but it may differ between compilers. Each - * compiler is supposed to document its behaviour in that respect. GCC - * explicitly defines that an arithmetic right shift is used. We expect - * all other compilers to do the same, because underlying CPU offer an - * arithmetic right shift opcode that could not be used otherwise. - */ -#if BR_NO_ARITH_SHIFT -#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ - | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) -#else -#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) -#endif - -/* - * Convert an integer from unsigned little-endian encoding to a sequence of - * 13-bit words in little-endian order. The final "partial" word is - * returned. - */ -static uint32_t -le8_to_le13(uint32_t *dst, const unsigned char *src, size_t len) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - acc |= (uint32_t)(*src ++) << acc_len; - acc_len += 8; - if (acc_len >= 13) { - *dst ++ = acc & 0x1FFF; - acc >>= 13; - acc_len -= 13; - } - } - return acc; -} - -/* - * Convert an integer (13-bit words, little-endian) to unsigned - * little-endian encoding. The total encoding length is provided; all - * the destination bytes will be filled. - */ -static void -le13_to_le8(unsigned char *dst, size_t len, const uint32_t *src) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - if (acc_len < 8) { - acc |= (*src ++) << acc_len; - acc_len += 13; - } - *dst ++ = (unsigned char)acc; - acc >>= 8; - acc_len -= 8; - } -} - -/* - * Normalise an array of words to a strict 13 bits per word. Returned - * value is the resulting carry. The source (w) and destination (d) - * arrays may be identical, but shall not overlap partially. - */ -static inline uint32_t -norm13(uint32_t *d, const uint32_t *w, size_t len) -{ - size_t u; - uint32_t cc; - - cc = 0; - for (u = 0; u < len; u ++) { - int32_t z; - - z = w[u] + cc; - d[u] = z & 0x1FFF; - cc = ARSH(z, 13); - } - return cc; -} - -/* - * mul20() multiplies two 260-bit integers together. Each word must fit - * on 13 bits; source operands use 20 words, destination operand - * receives 40 words. All overlaps allowed. - * - * square20() computes the square of a 260-bit integer. Each word must - * fit on 13 bits; source operand uses 20 words, destination operand - * receives 40 words. All overlaps allowed. - */ - -#if BR_SLOW_MUL15 - -static void -mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * Two-level Karatsuba: turns a 20x20 multiplication into - * nine 5x5 multiplications. We use 13-bit words but do not - * propagate carries immediately, so words may expand: - * - * - First Karatsuba decomposition turns the 20x20 mul on - * 13-bit words into three 10x10 muls, two on 13-bit words - * and one on 14-bit words. - * - * - Second Karatsuba decomposition further splits these into: - * - * * four 5x5 muls on 13-bit words - * * four 5x5 muls on 14-bit words - * * one 5x5 mul on 15-bit words - * - * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit - * or 15-bit words, respectively. - */ - uint32_t u[45], v[45], w[90]; - uint32_t cc; - int i; - -#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ - (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \ - + (s2w)[5 * (s2_off) + 0]; \ - (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \ - + (s2w)[5 * (s2_off) + 1]; \ - (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \ - + (s2w)[5 * (s2_off) + 2]; \ - (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \ - + (s2w)[5 * (s2_off) + 3]; \ - (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \ - + (s2w)[5 * (s2_off) + 4]; \ - } while (0) - -#define ZADDT(dw, d_off, sw, s_off) do { \ - (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \ - (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \ - (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \ - (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \ - (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \ - } while (0) - -#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ - (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \ - + (s2w)[5 * (s2_off) + 0]; \ - (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \ - + (s2w)[5 * (s2_off) + 1]; \ - (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \ - + (s2w)[5 * (s2_off) + 2]; \ - (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \ - + (s2w)[5 * (s2_off) + 3]; \ - (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \ - + (s2w)[5 * (s2_off) + 4]; \ - } while (0) - -#define CPR1(w, cprcc) do { \ - uint32_t cprz = (w) + cprcc; \ - (w) = cprz & 0x1FFF; \ - cprcc = cprz >> 13; \ - } while (0) - -#define CPR(dw, d_off) do { \ - uint32_t cprcc; \ - cprcc = 0; \ - CPR1((dw)[(d_off) + 0], cprcc); \ - CPR1((dw)[(d_off) + 1], cprcc); \ - CPR1((dw)[(d_off) + 2], cprcc); \ - CPR1((dw)[(d_off) + 3], cprcc); \ - CPR1((dw)[(d_off) + 4], cprcc); \ - CPR1((dw)[(d_off) + 5], cprcc); \ - CPR1((dw)[(d_off) + 6], cprcc); \ - CPR1((dw)[(d_off) + 7], cprcc); \ - CPR1((dw)[(d_off) + 8], cprcc); \ - (dw)[(d_off) + 9] = cprcc; \ - } while (0) - - memcpy(u, a, 20 * sizeof *a); - ZADD(u, 4, a, 0, a, 1); - ZADD(u, 5, a, 2, a, 3); - ZADD(u, 6, a, 0, a, 2); - ZADD(u, 7, a, 1, a, 3); - ZADD(u, 8, u, 6, u, 7); - - memcpy(v, b, 20 * sizeof *b); - ZADD(v, 4, b, 0, b, 1); - ZADD(v, 5, b, 2, b, 3); - ZADD(v, 6, b, 0, b, 2); - ZADD(v, 7, b, 1, b, 3); - ZADD(v, 8, v, 6, v, 7); - - /* - * Do the eight first 8x8 muls. Source words are at most 16382 - * each, so we can add product results together "as is" in 32-bit - * words. - */ - for (i = 0; i < 40; i += 5) { - w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]); - w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1]) - + MUL15(u[i + 1], v[i + 0]); - w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2]) - + MUL15(u[i + 1], v[i + 1]) - + MUL15(u[i + 2], v[i + 0]); - w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3]) - + MUL15(u[i + 1], v[i + 2]) - + MUL15(u[i + 2], v[i + 1]) - + MUL15(u[i + 3], v[i + 0]); - w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4]) - + MUL15(u[i + 1], v[i + 3]) - + MUL15(u[i + 2], v[i + 2]) - + MUL15(u[i + 3], v[i + 1]) - + MUL15(u[i + 4], v[i + 0]); - w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4]) - + MUL15(u[i + 2], v[i + 3]) - + MUL15(u[i + 3], v[i + 2]) - + MUL15(u[i + 4], v[i + 1]); - w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4]) - + MUL15(u[i + 3], v[i + 3]) - + MUL15(u[i + 4], v[i + 2]); - w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4]) - + MUL15(u[i + 4], v[i + 3]); - w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]); - w[(i << 1) + 9] = 0; - } - - /* - * For the 9th multiplication, source words are up to 32764, - * so we must do some carry propagation. If we add up to - * 4 products and the carry is no more than 524224, then the - * result fits in 32 bits, and the next carry will be no more - * than 524224 (because 4*(32764^2)+524224 < 8192*524225). - * - * We thus just skip one of the products in the middle word, - * then do a carry propagation (this reduces words to 13 bits - * each, except possibly the last, which may use up to 17 bits - * or so), then add the missing product. - */ - w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]); - w[80 + 1] = MUL15(u[40 + 0], v[40 + 1]) - + MUL15(u[40 + 1], v[40 + 0]); - w[80 + 2] = MUL15(u[40 + 0], v[40 + 2]) - + MUL15(u[40 + 1], v[40 + 1]) - + MUL15(u[40 + 2], v[40 + 0]); - w[80 + 3] = MUL15(u[40 + 0], v[40 + 3]) - + MUL15(u[40 + 1], v[40 + 2]) - + MUL15(u[40 + 2], v[40 + 1]) - + MUL15(u[40 + 3], v[40 + 0]); - w[80 + 4] = MUL15(u[40 + 0], v[40 + 4]) - + MUL15(u[40 + 1], v[40 + 3]) - + MUL15(u[40 + 2], v[40 + 2]) - + MUL15(u[40 + 3], v[40 + 1]); - /* + MUL15(u[40 + 4], v[40 + 0]) */ - w[80 + 5] = MUL15(u[40 + 1], v[40 + 4]) - + MUL15(u[40 + 2], v[40 + 3]) - + MUL15(u[40 + 3], v[40 + 2]) - + MUL15(u[40 + 4], v[40 + 1]); - w[80 + 6] = MUL15(u[40 + 2], v[40 + 4]) - + MUL15(u[40 + 3], v[40 + 3]) - + MUL15(u[40 + 4], v[40 + 2]); - w[80 + 7] = MUL15(u[40 + 3], v[40 + 4]) - + MUL15(u[40 + 4], v[40 + 3]); - w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]); - - CPR(w, 80); - - w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]); - - /* - * The products on 14-bit words in slots 6 and 7 yield values - * up to 5*(16382^2) each, and we need to subtract two such - * values from the higher word. We need the subtraction to fit - * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit. - * However, 10*(16382^2) does not fit. So we must perform a - * bit of reduction here. - */ - CPR(w, 60); - CPR(w, 70); - - /* - * Recompose results. - */ - - /* 0..1*0..1 into 0..3 */ - ZSUB2F(w, 8, w, 0, w, 2); - ZSUB2F(w, 9, w, 1, w, 3); - ZADDT(w, 1, w, 8); - ZADDT(w, 2, w, 9); - - /* 2..3*2..3 into 4..7 */ - ZSUB2F(w, 10, w, 4, w, 6); - ZSUB2F(w, 11, w, 5, w, 7); - ZADDT(w, 5, w, 10); - ZADDT(w, 6, w, 11); - - /* (0..1+2..3)*(0..1+2..3) into 12..15 */ - ZSUB2F(w, 16, w, 12, w, 14); - ZSUB2F(w, 17, w, 13, w, 15); - ZADDT(w, 13, w, 16); - ZADDT(w, 14, w, 17); - - /* first-level recomposition */ - ZSUB2F(w, 12, w, 0, w, 4); - ZSUB2F(w, 13, w, 1, w, 5); - ZSUB2F(w, 14, w, 2, w, 6); - ZSUB2F(w, 15, w, 3, w, 7); - ZADDT(w, 2, w, 12); - ZADDT(w, 3, w, 13); - ZADDT(w, 4, w, 14); - ZADDT(w, 5, w, 15); - - /* - * Perform carry propagation to bring all words down to 13 bits. - */ - cc = norm13(d, w, 40); - d[39] += (cc << 13); - -#undef ZADD -#undef ZADDT -#undef ZSUB2F -#undef CPR1 -#undef CPR -} - -static inline void -square20(uint32_t *d, const uint32_t *a) -{ - mul20(d, a, a); -} - -#else - -static void -mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[39]; - - t[ 0] = MUL15(a[ 0], b[ 0]); - t[ 1] = MUL15(a[ 0], b[ 1]) - + MUL15(a[ 1], b[ 0]); - t[ 2] = MUL15(a[ 0], b[ 2]) - + MUL15(a[ 1], b[ 1]) - + MUL15(a[ 2], b[ 0]); - t[ 3] = MUL15(a[ 0], b[ 3]) - + MUL15(a[ 1], b[ 2]) - + MUL15(a[ 2], b[ 1]) - + MUL15(a[ 3], b[ 0]); - t[ 4] = MUL15(a[ 0], b[ 4]) - + MUL15(a[ 1], b[ 3]) - + MUL15(a[ 2], b[ 2]) - + MUL15(a[ 3], b[ 1]) - + MUL15(a[ 4], b[ 0]); - t[ 5] = MUL15(a[ 0], b[ 5]) - + MUL15(a[ 1], b[ 4]) - + MUL15(a[ 2], b[ 3]) - + MUL15(a[ 3], b[ 2]) - + MUL15(a[ 4], b[ 1]) - + MUL15(a[ 5], b[ 0]); - t[ 6] = MUL15(a[ 0], b[ 6]) - + MUL15(a[ 1], b[ 5]) - + MUL15(a[ 2], b[ 4]) - + MUL15(a[ 3], b[ 3]) - + MUL15(a[ 4], b[ 2]) - + MUL15(a[ 5], b[ 1]) - + MUL15(a[ 6], b[ 0]); - t[ 7] = MUL15(a[ 0], b[ 7]) - + MUL15(a[ 1], b[ 6]) - + MUL15(a[ 2], b[ 5]) - + MUL15(a[ 3], b[ 4]) - + MUL15(a[ 4], b[ 3]) - + MUL15(a[ 5], b[ 2]) - + MUL15(a[ 6], b[ 1]) - + MUL15(a[ 7], b[ 0]); - t[ 8] = MUL15(a[ 0], b[ 8]) - + MUL15(a[ 1], b[ 7]) - + MUL15(a[ 2], b[ 6]) - + MUL15(a[ 3], b[ 5]) - + MUL15(a[ 4], b[ 4]) - + MUL15(a[ 5], b[ 3]) - + MUL15(a[ 6], b[ 2]) - + MUL15(a[ 7], b[ 1]) - + MUL15(a[ 8], b[ 0]); - t[ 9] = MUL15(a[ 0], b[ 9]) - + MUL15(a[ 1], b[ 8]) - + MUL15(a[ 2], b[ 7]) - + MUL15(a[ 3], b[ 6]) - + MUL15(a[ 4], b[ 5]) - + MUL15(a[ 5], b[ 4]) - + MUL15(a[ 6], b[ 3]) - + MUL15(a[ 7], b[ 2]) - + MUL15(a[ 8], b[ 1]) - + MUL15(a[ 9], b[ 0]); - t[10] = MUL15(a[ 0], b[10]) - + MUL15(a[ 1], b[ 9]) - + MUL15(a[ 2], b[ 8]) - + MUL15(a[ 3], b[ 7]) - + MUL15(a[ 4], b[ 6]) - + MUL15(a[ 5], b[ 5]) - + MUL15(a[ 6], b[ 4]) - + MUL15(a[ 7], b[ 3]) - + MUL15(a[ 8], b[ 2]) - + MUL15(a[ 9], b[ 1]) - + MUL15(a[10], b[ 0]); - t[11] = MUL15(a[ 0], b[11]) - + MUL15(a[ 1], b[10]) - + MUL15(a[ 2], b[ 9]) - + MUL15(a[ 3], b[ 8]) - + MUL15(a[ 4], b[ 7]) - + MUL15(a[ 5], b[ 6]) - + MUL15(a[ 6], b[ 5]) - + MUL15(a[ 7], b[ 4]) - + MUL15(a[ 8], b[ 3]) - + MUL15(a[ 9], b[ 2]) - + MUL15(a[10], b[ 1]) - + MUL15(a[11], b[ 0]); - t[12] = MUL15(a[ 0], b[12]) - + MUL15(a[ 1], b[11]) - + MUL15(a[ 2], b[10]) - + MUL15(a[ 3], b[ 9]) - + MUL15(a[ 4], b[ 8]) - + MUL15(a[ 5], b[ 7]) - + MUL15(a[ 6], b[ 6]) - + MUL15(a[ 7], b[ 5]) - + MUL15(a[ 8], b[ 4]) - + MUL15(a[ 9], b[ 3]) - + MUL15(a[10], b[ 2]) - + MUL15(a[11], b[ 1]) - + MUL15(a[12], b[ 0]); - t[13] = MUL15(a[ 0], b[13]) - + MUL15(a[ 1], b[12]) - + MUL15(a[ 2], b[11]) - + MUL15(a[ 3], b[10]) - + MUL15(a[ 4], b[ 9]) - + MUL15(a[ 5], b[ 8]) - + MUL15(a[ 6], b[ 7]) - + MUL15(a[ 7], b[ 6]) - + MUL15(a[ 8], b[ 5]) - + MUL15(a[ 9], b[ 4]) - + MUL15(a[10], b[ 3]) - + MUL15(a[11], b[ 2]) - + MUL15(a[12], b[ 1]) - + MUL15(a[13], b[ 0]); - t[14] = MUL15(a[ 0], b[14]) - + MUL15(a[ 1], b[13]) - + MUL15(a[ 2], b[12]) - + MUL15(a[ 3], b[11]) - + MUL15(a[ 4], b[10]) - + MUL15(a[ 5], b[ 9]) - + MUL15(a[ 6], b[ 8]) - + MUL15(a[ 7], b[ 7]) - + MUL15(a[ 8], b[ 6]) - + MUL15(a[ 9], b[ 5]) - + MUL15(a[10], b[ 4]) - + MUL15(a[11], b[ 3]) - + MUL15(a[12], b[ 2]) - + MUL15(a[13], b[ 1]) - + MUL15(a[14], b[ 0]); - t[15] = MUL15(a[ 0], b[15]) - + MUL15(a[ 1], b[14]) - + MUL15(a[ 2], b[13]) - + MUL15(a[ 3], b[12]) - + MUL15(a[ 4], b[11]) - + MUL15(a[ 5], b[10]) - + MUL15(a[ 6], b[ 9]) - + MUL15(a[ 7], b[ 8]) - + MUL15(a[ 8], b[ 7]) - + MUL15(a[ 9], b[ 6]) - + MUL15(a[10], b[ 5]) - + MUL15(a[11], b[ 4]) - + MUL15(a[12], b[ 3]) - + MUL15(a[13], b[ 2]) - + MUL15(a[14], b[ 1]) - + MUL15(a[15], b[ 0]); - t[16] = MUL15(a[ 0], b[16]) - + MUL15(a[ 1], b[15]) - + MUL15(a[ 2], b[14]) - + MUL15(a[ 3], b[13]) - + MUL15(a[ 4], b[12]) - + MUL15(a[ 5], b[11]) - + MUL15(a[ 6], b[10]) - + MUL15(a[ 7], b[ 9]) - + MUL15(a[ 8], b[ 8]) - + MUL15(a[ 9], b[ 7]) - + MUL15(a[10], b[ 6]) - + MUL15(a[11], b[ 5]) - + MUL15(a[12], b[ 4]) - + MUL15(a[13], b[ 3]) - + MUL15(a[14], b[ 2]) - + MUL15(a[15], b[ 1]) - + MUL15(a[16], b[ 0]); - t[17] = MUL15(a[ 0], b[17]) - + MUL15(a[ 1], b[16]) - + MUL15(a[ 2], b[15]) - + MUL15(a[ 3], b[14]) - + MUL15(a[ 4], b[13]) - + MUL15(a[ 5], b[12]) - + MUL15(a[ 6], b[11]) - + MUL15(a[ 7], b[10]) - + MUL15(a[ 8], b[ 9]) - + MUL15(a[ 9], b[ 8]) - + MUL15(a[10], b[ 7]) - + MUL15(a[11], b[ 6]) - + MUL15(a[12], b[ 5]) - + MUL15(a[13], b[ 4]) - + MUL15(a[14], b[ 3]) - + MUL15(a[15], b[ 2]) - + MUL15(a[16], b[ 1]) - + MUL15(a[17], b[ 0]); - t[18] = MUL15(a[ 0], b[18]) - + MUL15(a[ 1], b[17]) - + MUL15(a[ 2], b[16]) - + MUL15(a[ 3], b[15]) - + MUL15(a[ 4], b[14]) - + MUL15(a[ 5], b[13]) - + MUL15(a[ 6], b[12]) - + MUL15(a[ 7], b[11]) - + MUL15(a[ 8], b[10]) - + MUL15(a[ 9], b[ 9]) - + MUL15(a[10], b[ 8]) - + MUL15(a[11], b[ 7]) - + MUL15(a[12], b[ 6]) - + MUL15(a[13], b[ 5]) - + MUL15(a[14], b[ 4]) - + MUL15(a[15], b[ 3]) - + MUL15(a[16], b[ 2]) - + MUL15(a[17], b[ 1]) - + MUL15(a[18], b[ 0]); - t[19] = MUL15(a[ 0], b[19]) - + MUL15(a[ 1], b[18]) - + MUL15(a[ 2], b[17]) - + MUL15(a[ 3], b[16]) - + MUL15(a[ 4], b[15]) - + MUL15(a[ 5], b[14]) - + MUL15(a[ 6], b[13]) - + MUL15(a[ 7], b[12]) - + MUL15(a[ 8], b[11]) - + MUL15(a[ 9], b[10]) - + MUL15(a[10], b[ 9]) - + MUL15(a[11], b[ 8]) - + MUL15(a[12], b[ 7]) - + MUL15(a[13], b[ 6]) - + MUL15(a[14], b[ 5]) - + MUL15(a[15], b[ 4]) - + MUL15(a[16], b[ 3]) - + MUL15(a[17], b[ 2]) - + MUL15(a[18], b[ 1]) - + MUL15(a[19], b[ 0]); - t[20] = MUL15(a[ 1], b[19]) - + MUL15(a[ 2], b[18]) - + MUL15(a[ 3], b[17]) - + MUL15(a[ 4], b[16]) - + MUL15(a[ 5], b[15]) - + MUL15(a[ 6], b[14]) - + MUL15(a[ 7], b[13]) - + MUL15(a[ 8], b[12]) - + MUL15(a[ 9], b[11]) - + MUL15(a[10], b[10]) - + MUL15(a[11], b[ 9]) - + MUL15(a[12], b[ 8]) - + MUL15(a[13], b[ 7]) - + MUL15(a[14], b[ 6]) - + MUL15(a[15], b[ 5]) - + MUL15(a[16], b[ 4]) - + MUL15(a[17], b[ 3]) - + MUL15(a[18], b[ 2]) - + MUL15(a[19], b[ 1]); - t[21] = MUL15(a[ 2], b[19]) - + MUL15(a[ 3], b[18]) - + MUL15(a[ 4], b[17]) - + MUL15(a[ 5], b[16]) - + MUL15(a[ 6], b[15]) - + MUL15(a[ 7], b[14]) - + MUL15(a[ 8], b[13]) - + MUL15(a[ 9], b[12]) - + MUL15(a[10], b[11]) - + MUL15(a[11], b[10]) - + MUL15(a[12], b[ 9]) - + MUL15(a[13], b[ 8]) - + MUL15(a[14], b[ 7]) - + MUL15(a[15], b[ 6]) - + MUL15(a[16], b[ 5]) - + MUL15(a[17], b[ 4]) - + MUL15(a[18], b[ 3]) - + MUL15(a[19], b[ 2]); - t[22] = MUL15(a[ 3], b[19]) - + MUL15(a[ 4], b[18]) - + MUL15(a[ 5], b[17]) - + MUL15(a[ 6], b[16]) - + MUL15(a[ 7], b[15]) - + MUL15(a[ 8], b[14]) - + MUL15(a[ 9], b[13]) - + MUL15(a[10], b[12]) - + MUL15(a[11], b[11]) - + MUL15(a[12], b[10]) - + MUL15(a[13], b[ 9]) - + MUL15(a[14], b[ 8]) - + MUL15(a[15], b[ 7]) - + MUL15(a[16], b[ 6]) - + MUL15(a[17], b[ 5]) - + MUL15(a[18], b[ 4]) - + MUL15(a[19], b[ 3]); - t[23] = MUL15(a[ 4], b[19]) - + MUL15(a[ 5], b[18]) - + MUL15(a[ 6], b[17]) - + MUL15(a[ 7], b[16]) - + MUL15(a[ 8], b[15]) - + MUL15(a[ 9], b[14]) - + MUL15(a[10], b[13]) - + MUL15(a[11], b[12]) - + MUL15(a[12], b[11]) - + MUL15(a[13], b[10]) - + MUL15(a[14], b[ 9]) - + MUL15(a[15], b[ 8]) - + MUL15(a[16], b[ 7]) - + MUL15(a[17], b[ 6]) - + MUL15(a[18], b[ 5]) - + MUL15(a[19], b[ 4]); - t[24] = MUL15(a[ 5], b[19]) - + MUL15(a[ 6], b[18]) - + MUL15(a[ 7], b[17]) - + MUL15(a[ 8], b[16]) - + MUL15(a[ 9], b[15]) - + MUL15(a[10], b[14]) - + MUL15(a[11], b[13]) - + MUL15(a[12], b[12]) - + MUL15(a[13], b[11]) - + MUL15(a[14], b[10]) - + MUL15(a[15], b[ 9]) - + MUL15(a[16], b[ 8]) - + MUL15(a[17], b[ 7]) - + MUL15(a[18], b[ 6]) - + MUL15(a[19], b[ 5]); - t[25] = MUL15(a[ 6], b[19]) - + MUL15(a[ 7], b[18]) - + MUL15(a[ 8], b[17]) - + MUL15(a[ 9], b[16]) - + MUL15(a[10], b[15]) - + MUL15(a[11], b[14]) - + MUL15(a[12], b[13]) - + MUL15(a[13], b[12]) - + MUL15(a[14], b[11]) - + MUL15(a[15], b[10]) - + MUL15(a[16], b[ 9]) - + MUL15(a[17], b[ 8]) - + MUL15(a[18], b[ 7]) - + MUL15(a[19], b[ 6]); - t[26] = MUL15(a[ 7], b[19]) - + MUL15(a[ 8], b[18]) - + MUL15(a[ 9], b[17]) - + MUL15(a[10], b[16]) - + MUL15(a[11], b[15]) - + MUL15(a[12], b[14]) - + MUL15(a[13], b[13]) - + MUL15(a[14], b[12]) - + MUL15(a[15], b[11]) - + MUL15(a[16], b[10]) - + MUL15(a[17], b[ 9]) - + MUL15(a[18], b[ 8]) - + MUL15(a[19], b[ 7]); - t[27] = MUL15(a[ 8], b[19]) - + MUL15(a[ 9], b[18]) - + MUL15(a[10], b[17]) - + MUL15(a[11], b[16]) - + MUL15(a[12], b[15]) - + MUL15(a[13], b[14]) - + MUL15(a[14], b[13]) - + MUL15(a[15], b[12]) - + MUL15(a[16], b[11]) - + MUL15(a[17], b[10]) - + MUL15(a[18], b[ 9]) - + MUL15(a[19], b[ 8]); - t[28] = MUL15(a[ 9], b[19]) - + MUL15(a[10], b[18]) - + MUL15(a[11], b[17]) - + MUL15(a[12], b[16]) - + MUL15(a[13], b[15]) - + MUL15(a[14], b[14]) - + MUL15(a[15], b[13]) - + MUL15(a[16], b[12]) - + MUL15(a[17], b[11]) - + MUL15(a[18], b[10]) - + MUL15(a[19], b[ 9]); - t[29] = MUL15(a[10], b[19]) - + MUL15(a[11], b[18]) - + MUL15(a[12], b[17]) - + MUL15(a[13], b[16]) - + MUL15(a[14], b[15]) - + MUL15(a[15], b[14]) - + MUL15(a[16], b[13]) - + MUL15(a[17], b[12]) - + MUL15(a[18], b[11]) - + MUL15(a[19], b[10]); - t[30] = MUL15(a[11], b[19]) - + MUL15(a[12], b[18]) - + MUL15(a[13], b[17]) - + MUL15(a[14], b[16]) - + MUL15(a[15], b[15]) - + MUL15(a[16], b[14]) - + MUL15(a[17], b[13]) - + MUL15(a[18], b[12]) - + MUL15(a[19], b[11]); - t[31] = MUL15(a[12], b[19]) - + MUL15(a[13], b[18]) - + MUL15(a[14], b[17]) - + MUL15(a[15], b[16]) - + MUL15(a[16], b[15]) - + MUL15(a[17], b[14]) - + MUL15(a[18], b[13]) - + MUL15(a[19], b[12]); - t[32] = MUL15(a[13], b[19]) - + MUL15(a[14], b[18]) - + MUL15(a[15], b[17]) - + MUL15(a[16], b[16]) - + MUL15(a[17], b[15]) - + MUL15(a[18], b[14]) - + MUL15(a[19], b[13]); - t[33] = MUL15(a[14], b[19]) - + MUL15(a[15], b[18]) - + MUL15(a[16], b[17]) - + MUL15(a[17], b[16]) - + MUL15(a[18], b[15]) - + MUL15(a[19], b[14]); - t[34] = MUL15(a[15], b[19]) - + MUL15(a[16], b[18]) - + MUL15(a[17], b[17]) - + MUL15(a[18], b[16]) - + MUL15(a[19], b[15]); - t[35] = MUL15(a[16], b[19]) - + MUL15(a[17], b[18]) - + MUL15(a[18], b[17]) - + MUL15(a[19], b[16]); - t[36] = MUL15(a[17], b[19]) - + MUL15(a[18], b[18]) - + MUL15(a[19], b[17]); - t[37] = MUL15(a[18], b[19]) - + MUL15(a[19], b[18]); - t[38] = MUL15(a[19], b[19]); - - d[39] = norm13(d, t, 39); -} - -static void -square20(uint32_t *d, const uint32_t *a) -{ - uint32_t t[39]; - - t[ 0] = MUL15(a[ 0], a[ 0]); - t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1); - t[ 2] = MUL15(a[ 1], a[ 1]) - + ((MUL15(a[ 0], a[ 2])) << 1); - t[ 3] = ((MUL15(a[ 0], a[ 3]) - + MUL15(a[ 1], a[ 2])) << 1); - t[ 4] = MUL15(a[ 2], a[ 2]) - + ((MUL15(a[ 0], a[ 4]) - + MUL15(a[ 1], a[ 3])) << 1); - t[ 5] = ((MUL15(a[ 0], a[ 5]) - + MUL15(a[ 1], a[ 4]) - + MUL15(a[ 2], a[ 3])) << 1); - t[ 6] = MUL15(a[ 3], a[ 3]) - + ((MUL15(a[ 0], a[ 6]) - + MUL15(a[ 1], a[ 5]) - + MUL15(a[ 2], a[ 4])) << 1); - t[ 7] = ((MUL15(a[ 0], a[ 7]) - + MUL15(a[ 1], a[ 6]) - + MUL15(a[ 2], a[ 5]) - + MUL15(a[ 3], a[ 4])) << 1); - t[ 8] = MUL15(a[ 4], a[ 4]) - + ((MUL15(a[ 0], a[ 8]) - + MUL15(a[ 1], a[ 7]) - + MUL15(a[ 2], a[ 6]) - + MUL15(a[ 3], a[ 5])) << 1); - t[ 9] = ((MUL15(a[ 0], a[ 9]) - + MUL15(a[ 1], a[ 8]) - + MUL15(a[ 2], a[ 7]) - + MUL15(a[ 3], a[ 6]) - + MUL15(a[ 4], a[ 5])) << 1); - t[10] = MUL15(a[ 5], a[ 5]) - + ((MUL15(a[ 0], a[10]) - + MUL15(a[ 1], a[ 9]) - + MUL15(a[ 2], a[ 8]) - + MUL15(a[ 3], a[ 7]) - + MUL15(a[ 4], a[ 6])) << 1); - t[11] = ((MUL15(a[ 0], a[11]) - + MUL15(a[ 1], a[10]) - + MUL15(a[ 2], a[ 9]) - + MUL15(a[ 3], a[ 8]) - + MUL15(a[ 4], a[ 7]) - + MUL15(a[ 5], a[ 6])) << 1); - t[12] = MUL15(a[ 6], a[ 6]) - + ((MUL15(a[ 0], a[12]) - + MUL15(a[ 1], a[11]) - + MUL15(a[ 2], a[10]) - + MUL15(a[ 3], a[ 9]) - + MUL15(a[ 4], a[ 8]) - + MUL15(a[ 5], a[ 7])) << 1); - t[13] = ((MUL15(a[ 0], a[13]) - + MUL15(a[ 1], a[12]) - + MUL15(a[ 2], a[11]) - + MUL15(a[ 3], a[10]) - + MUL15(a[ 4], a[ 9]) - + MUL15(a[ 5], a[ 8]) - + MUL15(a[ 6], a[ 7])) << 1); - t[14] = MUL15(a[ 7], a[ 7]) - + ((MUL15(a[ 0], a[14]) - + MUL15(a[ 1], a[13]) - + MUL15(a[ 2], a[12]) - + MUL15(a[ 3], a[11]) - + MUL15(a[ 4], a[10]) - + MUL15(a[ 5], a[ 9]) - + MUL15(a[ 6], a[ 8])) << 1); - t[15] = ((MUL15(a[ 0], a[15]) - + MUL15(a[ 1], a[14]) - + MUL15(a[ 2], a[13]) - + MUL15(a[ 3], a[12]) - + MUL15(a[ 4], a[11]) - + MUL15(a[ 5], a[10]) - + MUL15(a[ 6], a[ 9]) - + MUL15(a[ 7], a[ 8])) << 1); - t[16] = MUL15(a[ 8], a[ 8]) - + ((MUL15(a[ 0], a[16]) - + MUL15(a[ 1], a[15]) - + MUL15(a[ 2], a[14]) - + MUL15(a[ 3], a[13]) - + MUL15(a[ 4], a[12]) - + MUL15(a[ 5], a[11]) - + MUL15(a[ 6], a[10]) - + MUL15(a[ 7], a[ 9])) << 1); - t[17] = ((MUL15(a[ 0], a[17]) - + MUL15(a[ 1], a[16]) - + MUL15(a[ 2], a[15]) - + MUL15(a[ 3], a[14]) - + MUL15(a[ 4], a[13]) - + MUL15(a[ 5], a[12]) - + MUL15(a[ 6], a[11]) - + MUL15(a[ 7], a[10]) - + MUL15(a[ 8], a[ 9])) << 1); - t[18] = MUL15(a[ 9], a[ 9]) - + ((MUL15(a[ 0], a[18]) - + MUL15(a[ 1], a[17]) - + MUL15(a[ 2], a[16]) - + MUL15(a[ 3], a[15]) - + MUL15(a[ 4], a[14]) - + MUL15(a[ 5], a[13]) - + MUL15(a[ 6], a[12]) - + MUL15(a[ 7], a[11]) - + MUL15(a[ 8], a[10])) << 1); - t[19] = ((MUL15(a[ 0], a[19]) - + MUL15(a[ 1], a[18]) - + MUL15(a[ 2], a[17]) - + MUL15(a[ 3], a[16]) - + MUL15(a[ 4], a[15]) - + MUL15(a[ 5], a[14]) - + MUL15(a[ 6], a[13]) - + MUL15(a[ 7], a[12]) - + MUL15(a[ 8], a[11]) - + MUL15(a[ 9], a[10])) << 1); - t[20] = MUL15(a[10], a[10]) - + ((MUL15(a[ 1], a[19]) - + MUL15(a[ 2], a[18]) - + MUL15(a[ 3], a[17]) - + MUL15(a[ 4], a[16]) - + MUL15(a[ 5], a[15]) - + MUL15(a[ 6], a[14]) - + MUL15(a[ 7], a[13]) - + MUL15(a[ 8], a[12]) - + MUL15(a[ 9], a[11])) << 1); - t[21] = ((MUL15(a[ 2], a[19]) - + MUL15(a[ 3], a[18]) - + MUL15(a[ 4], a[17]) - + MUL15(a[ 5], a[16]) - + MUL15(a[ 6], a[15]) - + MUL15(a[ 7], a[14]) - + MUL15(a[ 8], a[13]) - + MUL15(a[ 9], a[12]) - + MUL15(a[10], a[11])) << 1); - t[22] = MUL15(a[11], a[11]) - + ((MUL15(a[ 3], a[19]) - + MUL15(a[ 4], a[18]) - + MUL15(a[ 5], a[17]) - + MUL15(a[ 6], a[16]) - + MUL15(a[ 7], a[15]) - + MUL15(a[ 8], a[14]) - + MUL15(a[ 9], a[13]) - + MUL15(a[10], a[12])) << 1); - t[23] = ((MUL15(a[ 4], a[19]) - + MUL15(a[ 5], a[18]) - + MUL15(a[ 6], a[17]) - + MUL15(a[ 7], a[16]) - + MUL15(a[ 8], a[15]) - + MUL15(a[ 9], a[14]) - + MUL15(a[10], a[13]) - + MUL15(a[11], a[12])) << 1); - t[24] = MUL15(a[12], a[12]) - + ((MUL15(a[ 5], a[19]) - + MUL15(a[ 6], a[18]) - + MUL15(a[ 7], a[17]) - + MUL15(a[ 8], a[16]) - + MUL15(a[ 9], a[15]) - + MUL15(a[10], a[14]) - + MUL15(a[11], a[13])) << 1); - t[25] = ((MUL15(a[ 6], a[19]) - + MUL15(a[ 7], a[18]) - + MUL15(a[ 8], a[17]) - + MUL15(a[ 9], a[16]) - + MUL15(a[10], a[15]) - + MUL15(a[11], a[14]) - + MUL15(a[12], a[13])) << 1); - t[26] = MUL15(a[13], a[13]) - + ((MUL15(a[ 7], a[19]) - + MUL15(a[ 8], a[18]) - + MUL15(a[ 9], a[17]) - + MUL15(a[10], a[16]) - + MUL15(a[11], a[15]) - + MUL15(a[12], a[14])) << 1); - t[27] = ((MUL15(a[ 8], a[19]) - + MUL15(a[ 9], a[18]) - + MUL15(a[10], a[17]) - + MUL15(a[11], a[16]) - + MUL15(a[12], a[15]) - + MUL15(a[13], a[14])) << 1); - t[28] = MUL15(a[14], a[14]) - + ((MUL15(a[ 9], a[19]) - + MUL15(a[10], a[18]) - + MUL15(a[11], a[17]) - + MUL15(a[12], a[16]) - + MUL15(a[13], a[15])) << 1); - t[29] = ((MUL15(a[10], a[19]) - + MUL15(a[11], a[18]) - + MUL15(a[12], a[17]) - + MUL15(a[13], a[16]) - + MUL15(a[14], a[15])) << 1); - t[30] = MUL15(a[15], a[15]) - + ((MUL15(a[11], a[19]) - + MUL15(a[12], a[18]) - + MUL15(a[13], a[17]) - + MUL15(a[14], a[16])) << 1); - t[31] = ((MUL15(a[12], a[19]) - + MUL15(a[13], a[18]) - + MUL15(a[14], a[17]) - + MUL15(a[15], a[16])) << 1); - t[32] = MUL15(a[16], a[16]) - + ((MUL15(a[13], a[19]) - + MUL15(a[14], a[18]) - + MUL15(a[15], a[17])) << 1); - t[33] = ((MUL15(a[14], a[19]) - + MUL15(a[15], a[18]) - + MUL15(a[16], a[17])) << 1); - t[34] = MUL15(a[17], a[17]) - + ((MUL15(a[15], a[19]) - + MUL15(a[16], a[18])) << 1); - t[35] = ((MUL15(a[16], a[19]) - + MUL15(a[17], a[18])) << 1); - t[36] = MUL15(a[18], a[18]) - + ((MUL15(a[17], a[19])) << 1); - t[37] = ((MUL15(a[18], a[19])) << 1); - t[38] = MUL15(a[19], a[19]); - - d[39] = norm13(d, t, 39); -} - -#endif - -/* - * Perform a "final reduction" in field F255 (field for Curve25519) - * The source value must be less than twice the modulus. If the value - * is not lower than the modulus, then the modulus is subtracted and - * this function returns 1; otherwise, it leaves it untouched and it - * returns 0. - */ -static uint32_t -reduce_final_f255(uint32_t *d) -{ - uint32_t t[20]; - uint32_t cc; - int i; - - memcpy(t, d, sizeof t); - cc = 19; - for (i = 0; i < 20; i ++) { - uint32_t w; - - w = t[i] + cc; - cc = w >> 13; - t[i] = w & 0x1FFF; - } - cc = t[19] >> 8; - t[19] &= 0xFF; - CCOPY(cc, d, t, sizeof t); - return cc; -} - -static void -f255_mulgen(uint32_t *d, const uint32_t *a, const uint32_t *b, int square) -{ - uint32_t t[40], cc, w; - - /* - * Compute raw multiplication. All result words fit in 13 bits - * each; upper word (t[39]) must fit on 5 bits, since the product - * of two 256-bit integers must fit on 512 bits. - */ - if (square) { - square20(t, a); - } else { - mul20(t, a, b); - } - - /* - * Modular reduction: each high word is added where necessary. - * Since the modulus is 2^255-19 and word 20 corresponds to - * offset 20*13 = 260, word 20+k must be added to word k with - * a factor of 19*2^5 = 608. The extra bits in word 19 are also - * added that way. - */ - cc = MUL15(t[19] >> 8, 19); - t[19] &= 0xFF; - -#define MM1(x) do { \ - w = t[x] + cc + MUL15(t[(x) + 20], 608); \ - t[x] = w & 0x1FFF; \ - cc = w >> 13; \ - } while (0) - - MM1( 0); - MM1( 1); - MM1( 2); - MM1( 3); - MM1( 4); - MM1( 5); - MM1( 6); - MM1( 7); - MM1( 8); - MM1( 9); - MM1(10); - MM1(11); - MM1(12); - MM1(13); - MM1(14); - MM1(15); - MM1(16); - MM1(17); - MM1(18); - MM1(19); - -#undef MM1 - - cc = MUL15(w >> 8, 19); - t[19] &= 0xFF; - -#define MM2(x) do { \ - w = t[x] + cc; \ - d[x] = w & 0x1FFF; \ - cc = w >> 13; \ - } while (0) - - MM2( 0); - MM2( 1); - MM2( 2); - MM2( 3); - MM2( 4); - MM2( 5); - MM2( 6); - MM2( 7); - MM2( 8); - MM2( 9); - MM2(10); - MM2(11); - MM2(12); - MM2(13); - MM2(14); - MM2(15); - MM2(16); - MM2(17); - MM2(18); - MM2(19); - -#undef MM2 -} - -/* - * Perform a multiplication of two integers modulo 2^255-19. - * Operands are arrays of 20 words, each containing 13 bits of data, in - * little-endian order. Input value may be up to 2^256-1; on output, value - * fits on 256 bits and is lower than twice the modulus. - * - * f255_mul() is the general multiplication, f255_square() is specialised - * for squarings. - */ -#define f255_mul(d, a, b) f255_mulgen(d, a, b, 0) -#define f255_square(d, a) f255_mulgen(d, a, a, 1) - -/* - * Add two values in F255. Partial reduction is performed (down to less - * than twice the modulus). - */ -static void -f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - int i; - uint32_t cc, w; - - cc = 0; - for (i = 0; i < 20; i ++) { - w = a[i] + b[i] + cc; - d[i] = w & 0x1FFF; - cc = w >> 13; - } - cc = MUL15(w >> 8, 19); - d[19] &= 0xFF; - for (i = 0; i < 20; i ++) { - w = d[i] + cc; - d[i] = w & 0x1FFF; - cc = w >> 13; - } -} - -/* - * Subtract one value from another in F255. Partial reduction is - * performed (down to less than twice the modulus). - */ -static void -f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * We actually compute a - b + 2*p, so that the final value is - * necessarily positive. - */ - int i; - uint32_t cc, w; - - cc = (uint32_t)-38; - for (i = 0; i < 20; i ++) { - w = a[i] - b[i] + cc; - d[i] = w & 0x1FFF; - cc = ARSH(w, 13); - } - cc = MUL15((w + 0x200) >> 8, 19); - d[19] &= 0xFF; - for (i = 0; i < 20; i ++) { - w = d[i] + cc; - d[i] = w & 0x1FFF; - cc = w >> 13; - } -} - -/* - * Multiply an integer by the 'A24' constant (121665). Partial reduction - * is performed (down to less than twice the modulus). - */ -static void -f255_mul_a24(uint32_t *d, const uint32_t *a) -{ - int i; - uint32_t cc, w; - - cc = 0; - for (i = 0; i < 20; i ++) { - w = MUL15(a[i], 121665) + cc; - d[i] = w & 0x1FFF; - cc = w >> 13; - } - cc = MUL15(w >> 8, 19); - d[19] &= 0xFF; - for (i = 0; i < 20; i ++) { - w = d[i] + cc; - d[i] = w & 0x1FFF; - cc = w >> 13; - } -} - -static const unsigned char GEN[] = { - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char ORDER[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return GEN; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return ORDER; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 0; -} - -static void -cswap(uint32_t *a, uint32_t *b, uint32_t ctl) -{ - int i; - - ctl = -ctl; - for (i = 0; i < 20; i ++) { - uint32_t aw, bw, tw; - - aw = a[i]; - bw = b[i]; - tw = ctl & (aw ^ bw); - a[i] = aw ^ tw; - b[i] = bw ^ tw; - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ - uint32_t x1[20], x2[20], x3[20], z2[20], z3[20]; - uint32_t a[20], aa[20], b[20], bb[20]; - uint32_t c[20], d[20], e[20], da[20], cb[20]; - unsigned char k[32]; - uint32_t swap; - int i; - - (void)curve; - - /* - * Points are encoded over exactly 32 bytes. Multipliers must fit - * in 32 bytes as well. - * RFC 7748 mandates that the high bit of the last point byte must - * be ignored/cleared. - */ - if (Glen != 32 || kblen > 32) { - return 0; - } - G[31] &= 0x7F; - - /* - * Initialise variables x1, x2, z2, x3 and z3. We set all of them - * into Montgomery representation. - */ - x1[19] = le8_to_le13(x1, G, 32); - memcpy(x3, x1, sizeof x1); - memset(z2, 0, sizeof z2); - memset(x2, 0, sizeof x2); - x2[0] = 1; - memset(z3, 0, sizeof z3); - z3[0] = 1; - - memcpy(k, kb, kblen); - memset(k + kblen, 0, (sizeof k) - kblen); - k[0] &= 0xF8; - k[31] &= 0x7F; - k[31] |= 0x40; - - /* obsolete - print_int("x1", x1); - */ - - swap = 0; - for (i = 254; i >= 0; i --) { - uint32_t kt; - - kt = (k[i >> 3] >> (i & 7)) & 1; - swap ^= kt; - cswap(x2, x3, swap); - cswap(z2, z3, swap); - swap = kt; - - /* obsolete - print_int("x2", x2); - print_int("z2", z2); - print_int("x3", x3); - print_int("z3", z3); - */ - - f255_add(a, x2, z2); - f255_square(aa, a); - f255_sub(b, x2, z2); - f255_square(bb, b); - f255_sub(e, aa, bb); - f255_add(c, x3, z3); - f255_sub(d, x3, z3); - f255_mul(da, d, a); - f255_mul(cb, c, b); - - /* obsolete - print_int("a ", a); - print_int("aa", aa); - print_int("b ", b); - print_int("bb", bb); - print_int("e ", e); - print_int("c ", c); - print_int("d ", d); - print_int("da", da); - print_int("cb", cb); - */ - - f255_add(x3, da, cb); - f255_square(x3, x3); - f255_sub(z3, da, cb); - f255_square(z3, z3); - f255_mul(z3, z3, x1); - f255_mul(x2, aa, bb); - f255_mul_a24(z2, e); - f255_add(z2, z2, aa); - f255_mul(z2, e, z2); - - /* obsolete - print_int("x2", x2); - print_int("z2", z2); - print_int("x3", x3); - print_int("z3", z3); - */ - } - cswap(x2, x3, swap); - cswap(z2, z3, swap); - - /* - * Inverse z2 with a modular exponentiation. This is a simple - * square-and-multiply algorithm; we mutualise most non-squarings - * since the exponent contains almost only ones. - */ - memcpy(a, z2, sizeof z2); - for (i = 0; i < 15; i ++) { - f255_square(a, a); - f255_mul(a, a, z2); - } - memcpy(b, a, sizeof a); - for (i = 0; i < 14; i ++) { - int j; - - for (j = 0; j < 16; j ++) { - f255_square(b, b); - } - f255_mul(b, b, a); - } - for (i = 14; i >= 0; i --) { - f255_square(b, b); - if ((0xFFEB >> i) & 1) { - f255_mul(b, z2, b); - } - } - f255_mul(x2, x2, b); - reduce_final_f255(x2); - le13_to_le8(G, 32, x2); - return 1; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - /* - * We don't implement this method, since it is used for ECDSA - * only, and there is no ECDSA over Curve25519 (which instead - * uses EdDSA). - */ - (void)A; - (void)B; - (void)len; - (void)x; - (void)xlen; - (void)y; - (void)ylen; - (void)curve; - return 0; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_c25519_m15 = { - (uint32_t)0x20000000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_c25519_m31.c b/src/tls/bearssl/ec_c25519_m31.c deleted file mode 100644 index c1497bd25..000000000 --- a/src/tls/bearssl/ec_c25519_m31.c +++ /dev/null @@ -1,774 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* obsolete -#include -#include -static void -print_int(const char *name, const uint32_t *x) -{ - size_t u; - unsigned char tmp[40]; - - printf("%s = ", name); - for (u = 0; u < 9; u ++) { - if (x[u] > 0x3FFFFFFF) { - printf("INVALID:"); - for (u = 0; u < 9; u ++) { - printf(" %08X", x[u]); - } - printf("\n"); - return; - } - } - memset(tmp, 0, sizeof tmp); - for (u = 0; u < 9; u ++) { - uint64_t w; - int j, k; - - w = x[u]; - j = 30 * (int)u; - k = j & 7; - if (k != 0) { - w <<= k; - j -= k; - } - k = j >> 3; - for (j = 0; j < 8; j ++) { - tmp[39 - k - j] |= (unsigned char)w; - w >>= 8; - } - } - for (u = 8; u < 40; u ++) { - printf("%02X", tmp[u]); - } - printf("\n"); -} -*/ - -/* - * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ - * that right-shifting a signed negative integer copies the sign bit - * (arithmetic right-shift). This is "implementation-defined behaviour", - * i.e. it is not undefined, but it may differ between compilers. Each - * compiler is supposed to document its behaviour in that respect. GCC - * explicitly defines that an arithmetic right shift is used. We expect - * all other compilers to do the same, because underlying CPU offer an - * arithmetic right shift opcode that could not be used otherwise. - */ -#if BR_NO_ARITH_SHIFT -#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ - | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) -#else -#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) -#endif - -/* - * Convert an integer from unsigned little-endian encoding to a sequence of - * 30-bit words in little-endian order. The final "partial" word is - * returned. - */ -static uint32_t -le8_to_le30(uint32_t *dst, const unsigned char *src, size_t len) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - uint32_t b; - - b = *src ++; - if (acc_len < 22) { - acc |= b << acc_len; - acc_len += 8; - } else { - *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF; - acc = b >> (30 - acc_len); - acc_len -= 22; - } - } - return acc; -} - -/* - * Convert an integer (30-bit words, little-endian) to unsigned - * little-endian encoding. The total encoding length is provided; all - * the destination bytes will be filled. - */ -static void -le30_to_le8(unsigned char *dst, size_t len, const uint32_t *src) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - if (acc_len < 8) { - uint32_t w; - - w = *src ++; - *dst ++ = (unsigned char)(acc | (w << acc_len)); - acc = w >> (8 - acc_len); - acc_len += 22; - } else { - *dst ++ = (unsigned char)acc; - acc >>= 8; - acc_len -= 8; - } - } -} - -/* - * Multiply two integers. Source integers are represented as arrays of - * nine 30-bit words, for values up to 2^270-1. Result is encoded over - * 18 words of 30 bits each. - */ -static void -mul9(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * Maximum intermediate result is no more than - * 10376293531797946367, which fits in 64 bits. Reason: - * - * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406 - * 10376293531797946367 < 9663676407 * 2^30 - * - * Thus, adding together 9 products of 30-bit integers, with - * a carry of at most 9663676406, yields an integer that fits - * on 64 bits and generates a carry of at most 9663676406. - */ - uint64_t t[17]; - uint64_t cc; - int i; - - t[ 0] = MUL31(a[0], b[0]); - t[ 1] = MUL31(a[0], b[1]) - + MUL31(a[1], b[0]); - t[ 2] = MUL31(a[0], b[2]) - + MUL31(a[1], b[1]) - + MUL31(a[2], b[0]); - t[ 3] = MUL31(a[0], b[3]) - + MUL31(a[1], b[2]) - + MUL31(a[2], b[1]) - + MUL31(a[3], b[0]); - t[ 4] = MUL31(a[0], b[4]) - + MUL31(a[1], b[3]) - + MUL31(a[2], b[2]) - + MUL31(a[3], b[1]) - + MUL31(a[4], b[0]); - t[ 5] = MUL31(a[0], b[5]) - + MUL31(a[1], b[4]) - + MUL31(a[2], b[3]) - + MUL31(a[3], b[2]) - + MUL31(a[4], b[1]) - + MUL31(a[5], b[0]); - t[ 6] = MUL31(a[0], b[6]) - + MUL31(a[1], b[5]) - + MUL31(a[2], b[4]) - + MUL31(a[3], b[3]) - + MUL31(a[4], b[2]) - + MUL31(a[5], b[1]) - + MUL31(a[6], b[0]); - t[ 7] = MUL31(a[0], b[7]) - + MUL31(a[1], b[6]) - + MUL31(a[2], b[5]) - + MUL31(a[3], b[4]) - + MUL31(a[4], b[3]) - + MUL31(a[5], b[2]) - + MUL31(a[6], b[1]) - + MUL31(a[7], b[0]); - t[ 8] = MUL31(a[0], b[8]) - + MUL31(a[1], b[7]) - + MUL31(a[2], b[6]) - + MUL31(a[3], b[5]) - + MUL31(a[4], b[4]) - + MUL31(a[5], b[3]) - + MUL31(a[6], b[2]) - + MUL31(a[7], b[1]) - + MUL31(a[8], b[0]); - t[ 9] = MUL31(a[1], b[8]) - + MUL31(a[2], b[7]) - + MUL31(a[3], b[6]) - + MUL31(a[4], b[5]) - + MUL31(a[5], b[4]) - + MUL31(a[6], b[3]) - + MUL31(a[7], b[2]) - + MUL31(a[8], b[1]); - t[10] = MUL31(a[2], b[8]) - + MUL31(a[3], b[7]) - + MUL31(a[4], b[6]) - + MUL31(a[5], b[5]) - + MUL31(a[6], b[4]) - + MUL31(a[7], b[3]) - + MUL31(a[8], b[2]); - t[11] = MUL31(a[3], b[8]) - + MUL31(a[4], b[7]) - + MUL31(a[5], b[6]) - + MUL31(a[6], b[5]) - + MUL31(a[7], b[4]) - + MUL31(a[8], b[3]); - t[12] = MUL31(a[4], b[8]) - + MUL31(a[5], b[7]) - + MUL31(a[6], b[6]) - + MUL31(a[7], b[5]) - + MUL31(a[8], b[4]); - t[13] = MUL31(a[5], b[8]) - + MUL31(a[6], b[7]) - + MUL31(a[7], b[6]) - + MUL31(a[8], b[5]); - t[14] = MUL31(a[6], b[8]) - + MUL31(a[7], b[7]) - + MUL31(a[8], b[6]); - t[15] = MUL31(a[7], b[8]) - + MUL31(a[8], b[7]); - t[16] = MUL31(a[8], b[8]); - - /* - * Propagate carries. - */ - cc = 0; - for (i = 0; i < 17; i ++) { - uint64_t w; - - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - d[17] = (uint32_t)cc; -} - -/* - * Square a 270-bit integer, represented as an array of nine 30-bit words. - * Result uses 18 words of 30 bits each. - */ -static void -square9(uint32_t *d, const uint32_t *a) -{ - uint64_t t[17]; - uint64_t cc; - int i; - - t[ 0] = MUL31(a[0], a[0]); - t[ 1] = ((MUL31(a[0], a[1])) << 1); - t[ 2] = MUL31(a[1], a[1]) - + ((MUL31(a[0], a[2])) << 1); - t[ 3] = ((MUL31(a[0], a[3]) - + MUL31(a[1], a[2])) << 1); - t[ 4] = MUL31(a[2], a[2]) - + ((MUL31(a[0], a[4]) - + MUL31(a[1], a[3])) << 1); - t[ 5] = ((MUL31(a[0], a[5]) - + MUL31(a[1], a[4]) - + MUL31(a[2], a[3])) << 1); - t[ 6] = MUL31(a[3], a[3]) - + ((MUL31(a[0], a[6]) - + MUL31(a[1], a[5]) - + MUL31(a[2], a[4])) << 1); - t[ 7] = ((MUL31(a[0], a[7]) - + MUL31(a[1], a[6]) - + MUL31(a[2], a[5]) - + MUL31(a[3], a[4])) << 1); - t[ 8] = MUL31(a[4], a[4]) - + ((MUL31(a[0], a[8]) - + MUL31(a[1], a[7]) - + MUL31(a[2], a[6]) - + MUL31(a[3], a[5])) << 1); - t[ 9] = ((MUL31(a[1], a[8]) - + MUL31(a[2], a[7]) - + MUL31(a[3], a[6]) - + MUL31(a[4], a[5])) << 1); - t[10] = MUL31(a[5], a[5]) - + ((MUL31(a[2], a[8]) - + MUL31(a[3], a[7]) - + MUL31(a[4], a[6])) << 1); - t[11] = ((MUL31(a[3], a[8]) - + MUL31(a[4], a[7]) - + MUL31(a[5], a[6])) << 1); - t[12] = MUL31(a[6], a[6]) - + ((MUL31(a[4], a[8]) - + MUL31(a[5], a[7])) << 1); - t[13] = ((MUL31(a[5], a[8]) - + MUL31(a[6], a[7])) << 1); - t[14] = MUL31(a[7], a[7]) - + ((MUL31(a[6], a[8])) << 1); - t[15] = ((MUL31(a[7], a[8])) << 1); - t[16] = MUL31(a[8], a[8]); - - /* - * Propagate carries. - */ - cc = 0; - for (i = 0; i < 17; i ++) { - uint64_t w; - - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - d[17] = (uint32_t)cc; -} - -/* - * Perform a "final reduction" in field F255 (field for Curve25519) - * The source value must be less than twice the modulus. If the value - * is not lower than the modulus, then the modulus is subtracted and - * this function returns 1; otherwise, it leaves it untouched and it - * returns 0. - */ -static uint32_t -reduce_final_f255(uint32_t *d) -{ - uint32_t t[9]; - uint32_t cc; - int i; - - memcpy(t, d, sizeof t); - cc = 19; - for (i = 0; i < 9; i ++) { - uint32_t w; - - w = t[i] + cc; - cc = w >> 30; - t[i] = w & 0x3FFFFFFF; - } - cc = t[8] >> 15; - t[8] &= 0x7FFF; - CCOPY(cc, d, t, sizeof t); - return cc; -} - -/* - * Perform a multiplication of two integers modulo 2^255-19. - * Operands are arrays of 9 words, each containing 30 bits of data, in - * little-endian order. Input value may be up to 2^256-1; on output, value - * fits on 256 bits and is lower than twice the modulus. - */ -static void -f255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[18]; - uint64_t cc, w; - int i; - - /* - * Compute raw multiplication. All result words fit in 30 bits - * each; upper word (t[17]) must fit on 2 bits, since the product - * of two 256-bit integers must fit on 512 bits. - */ - mul9(t, a, b); - - /* - * Modular reduction: each high word is added where necessary. - * Since the modulus is 2^255-19 and word 9 corresponds to - * offset 9*30 = 270, word 9+k must be added to word k with - * a factor of 19*2^15 = 622592. The extra bits in word 8 are also - * added that way. - */ - cc = MUL31(t[8] >> 15, 19); - t[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = (uint64_t)t[i] + cc + MUL31(t[i + 9], 622592); - t[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - cc = MUL31(w >> 15, 19); - t[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } -} - -/* - * Perform a squaring of an integer modulo 2^255-19. - * Operands are arrays of 9 words, each containing 30 bits of data, in - * little-endian order. Input value may be up to 2^256-1; on output, value - * fits on 256 bits and is lower than twice the modulus. - */ -static void -f255_square(uint32_t *d, const uint32_t *a) -{ - uint32_t t[18]; - uint64_t cc, w; - int i; - - /* - * Compute raw squaring. All result words fit in 30 bits - * each; upper word (t[17]) must fit on 2 bits, since the square - * of a 256-bit integers must fit on 512 bits. - */ - square9(t, a); - - /* - * Modular reduction: each high word is added where necessary. - * Since the modulus is 2^255-19 and word 9 corresponds to - * offset 9*30 = 270, word 9+k must be added to word k with - * a factor of 19*2^15 = 622592. The extra bits in word 8 are also - * added that way. - */ - cc = MUL31(t[8] >> 15, 19); - t[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = (uint64_t)t[i] + cc + MUL31(t[i + 9], 622592); - t[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - cc = MUL31(w >> 15, 19); - t[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } -} - -/* - * Add two values in F255. Partial reduction is performed (down to less - * than twice the modulus). - */ -static void -f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * Since operand words fit on 30 bits, we can use 32-bit - * variables throughout. - */ - int i; - uint32_t cc, w; - - cc = 0; - for (i = 0; i < 9; i ++) { - w = a[i] + b[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = w >> 30; - } - cc = MUL15(w >> 15, 19); - d[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = d[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = w >> 30; - } -} - -/* - * Subtract one value from another in F255. Partial reduction is - * performed (down to less than twice the modulus). - */ -static void -f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * We actually compute a - b + 2*p, so that the final value is - * necessarily positive. - */ - int i; - uint32_t cc, w; - - cc = (uint32_t)-38; - for (i = 0; i < 9; i ++) { - w = a[i] - b[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = ARSH(w, 30); - } - cc = MUL15((w + 0x10000) >> 15, 19); - d[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = d[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = w >> 30; - } -} - -/* - * Multiply an integer by the 'A24' constant (121665). Partial reduction - * is performed (down to less than twice the modulus). - */ -static void -f255_mul_a24(uint32_t *d, const uint32_t *a) -{ - int i; - uint64_t cc, w; - - cc = 0; - for (i = 0; i < 9; i ++) { - w = MUL31(a[i], 121665) + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - cc = MUL31((uint32_t)(w >> 15), 19); - d[8] &= 0x7FFF; - for (i = 0; i < 9; i ++) { - w = (uint64_t)d[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = w >> 30; - } -} - -static const unsigned char GEN[] = { - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char ORDER[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return GEN; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return ORDER; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 0; -} - -static void -cswap(uint32_t *a, uint32_t *b, uint32_t ctl) -{ - int i; - - ctl = -ctl; - for (i = 0; i < 9; i ++) { - uint32_t aw, bw, tw; - - aw = a[i]; - bw = b[i]; - tw = ctl & (aw ^ bw); - a[i] = aw ^ tw; - b[i] = bw ^ tw; - } -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *kb, size_t kblen, int curve) -{ - uint32_t x1[9], x2[9], x3[9], z2[9], z3[9]; - uint32_t a[9], aa[9], b[9], bb[9]; - uint32_t c[9], d[9], e[9], da[9], cb[9]; - unsigned char k[32]; - uint32_t swap; - int i; - - (void)curve; - - /* - * Points are encoded over exactly 32 bytes. Multipliers must fit - * in 32 bytes as well. - * RFC 7748 mandates that the high bit of the last point byte must - * be ignored/cleared. - */ - if (Glen != 32 || kblen > 32) { - return 0; - } - G[31] &= 0x7F; - - /* - * Initialise variables x1, x2, z2, x3 and z3. We set all of them - * into Montgomery representation. - */ - x1[8] = le8_to_le30(x1, G, 32); - memcpy(x3, x1, sizeof x1); - memset(z2, 0, sizeof z2); - memset(x2, 0, sizeof x2); - x2[0] = 1; - memset(z3, 0, sizeof z3); - z3[0] = 1; - - memcpy(k, kb, kblen); - memset(k + kblen, 0, (sizeof k) - kblen); - k[0] &= 0xF8; - k[31] &= 0x7F; - k[31] |= 0x40; - - /* obsolete - print_int("x1", x1); - */ - - swap = 0; - for (i = 254; i >= 0; i --) { - uint32_t kt; - - kt = (k[i >> 3] >> (i & 7)) & 1; - swap ^= kt; - cswap(x2, x3, swap); - cswap(z2, z3, swap); - swap = kt; - - /* obsolete - print_int("x2", x2); - print_int("z2", z2); - print_int("x3", x3); - print_int("z3", z3); - */ - - f255_add(a, x2, z2); - f255_square(aa, a); - f255_sub(b, x2, z2); - f255_square(bb, b); - f255_sub(e, aa, bb); - f255_add(c, x3, z3); - f255_sub(d, x3, z3); - f255_mul(da, d, a); - f255_mul(cb, c, b); - - /* obsolete - print_int("a ", a); - print_int("aa", aa); - print_int("b ", b); - print_int("bb", bb); - print_int("e ", e); - print_int("c ", c); - print_int("d ", d); - print_int("da", da); - print_int("cb", cb); - */ - - f255_add(x3, da, cb); - f255_square(x3, x3); - f255_sub(z3, da, cb); - f255_square(z3, z3); - f255_mul(z3, z3, x1); - f255_mul(x2, aa, bb); - f255_mul_a24(z2, e); - f255_add(z2, z2, aa); - f255_mul(z2, e, z2); - - /* obsolete - print_int("x2", x2); - print_int("z2", z2); - print_int("x3", x3); - print_int("z3", z3); - */ - } - cswap(x2, x3, swap); - cswap(z2, z3, swap); - - /* - * Inverse z2 with a modular exponentiation. This is a simple - * square-and-multiply algorithm; we mutualise most non-squarings - * since the exponent contains almost only ones. - */ - memcpy(a, z2, sizeof z2); - for (i = 0; i < 15; i ++) { - f255_square(a, a); - f255_mul(a, a, z2); - } - memcpy(b, a, sizeof a); - for (i = 0; i < 14; i ++) { - int j; - - for (j = 0; j < 16; j ++) { - f255_square(b, b); - } - f255_mul(b, b, a); - } - for (i = 14; i >= 0; i --) { - f255_square(b, b); - if ((0xFFEB >> i) & 1) { - f255_mul(b, z2, b); - } - } - f255_mul(x2, x2, b); - reduce_final_f255(x2); - le30_to_le8(G, 32, x2); - return 1; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - /* - * We don't implement this method, since it is used for ECDSA - * only, and there is no ECDSA over Curve25519 (which instead - * uses EdDSA). - */ - (void)A; - (void)B; - (void)len; - (void)x; - (void)xlen; - (void)y; - (void)ylen; - (void)curve; - return 0; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_c25519_m31 = { - (uint32_t)0x20000000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_curve25519.c b/src/tls/bearssl/ec_curve25519.c deleted file mode 100644 index b9318ef0b..000000000 --- a/src/tls/bearssl/ec_curve25519.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char GEN[] = { - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const unsigned char ORDER[] = { - 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -/* see inner.h */ -const br_ec_curve_def br_curve25519 = { - BR_EC_curve25519, - ORDER, sizeof ORDER, - GEN, sizeof GEN -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_default.c b/src/tls/bearssl/ec_default.c deleted file mode 100644 index d7d699d08..000000000 --- a/src/tls/bearssl/ec_default.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -const br_ec_impl * -br_ec_get_default(void) -{ -#if BR_LOMUL - return &br_ec_all_m15; -#else - return &br_ec_all_m31; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_keygen.c b/src/tls/bearssl/ec_keygen.c deleted file mode 100644 index 62e746905..000000000 --- a/src/tls/bearssl/ec_keygen.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -size_t -br_ec_keygen(const br_prng_class **rng_ctx, - const br_ec_impl *impl, br_ec_private_key *sk, - void *kbuf, int curve) -{ - const unsigned char *order; - unsigned char *buf; - size_t len; - unsigned mask; - - if (curve < 0 || curve >= 32 - || ((impl->supported_curves >> curve) & 1) == 0) - { - return 0; - } - order = impl->order(curve, &len); - while (len > 0 && *order == 0) { - order ++; - len --; - } - if (kbuf == NULL || len == 0) { - return len; - } - mask = order[0]; - mask |= (mask >> 1); - mask |= (mask >> 2); - mask |= (mask >> 4); - - /* - * We generate sequences of random bits of the right size, until - * the value is strictly lower than the curve order (we also - * check for all-zero values, which are invalid). - */ - buf = kbuf; - for (;;) { - size_t u; - unsigned cc, zz; - - (*rng_ctx)->generate(rng_ctx, buf, len); - buf[0] &= mask; - cc = 0; - u = len; - zz = 0; - while (u -- > 0) { - cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1; - zz |= buf[u]; - } - if (cc != 0 && zz != 0) { - break; - } - } - - if (sk != NULL) { - sk->curve = curve; - sk->x = buf; - sk->xlen = len; - } - return len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_p256_m15.c b/src/tls/bearssl/ec_p256_m15.c deleted file mode 100644 index 71709a68b..000000000 --- a/src/tls/bearssl/ec_p256_m15.c +++ /dev/null @@ -1,2135 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ - * that right-shifting a signed negative integer copies the sign bit - * (arithmetic right-shift). This is "implementation-defined behaviour", - * i.e. it is not undefined, but it may differ between compilers. Each - * compiler is supposed to document its behaviour in that respect. GCC - * explicitly defines that an arithmetic right shift is used. We expect - * all other compilers to do the same, because underlying CPU offer an - * arithmetic right shift opcode that could not be used otherwise. - */ -#if BR_NO_ARITH_SHIFT -#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ - | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) -#else -#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) -#endif - -/* - * Convert an integer from unsigned big-endian encoding to a sequence of - * 13-bit words in little-endian order. The final "partial" word is - * returned. - */ -static uint32_t -be8_to_le13(uint32_t *dst, const unsigned char *src, size_t len) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - acc |= (uint32_t)src[len] << acc_len; - acc_len += 8; - if (acc_len >= 13) { - *dst ++ = acc & 0x1FFF; - acc >>= 13; - acc_len -= 13; - } - } - return acc; -} - -/* - * Convert an integer (13-bit words, little-endian) to unsigned - * big-endian encoding. The total encoding length is provided; all - * the destination bytes will be filled. - */ -static void -le13_to_be8(unsigned char *dst, size_t len, const uint32_t *src) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - if (acc_len < 8) { - acc |= (*src ++) << acc_len; - acc_len += 13; - } - dst[len] = (unsigned char)acc; - acc >>= 8; - acc_len -= 8; - } -} - -/* - * Normalise an array of words to a strict 13 bits per word. Returned - * value is the resulting carry. The source (w) and destination (d) - * arrays may be identical, but shall not overlap partially. - */ -static inline uint32_t -norm13(uint32_t *d, const uint32_t *w, size_t len) -{ - size_t u; - uint32_t cc; - - cc = 0; - for (u = 0; u < len; u ++) { - int32_t z; - - z = w[u] + cc; - d[u] = z & 0x1FFF; - cc = ARSH(z, 13); - } - return cc; -} - -/* - * mul20() multiplies two 260-bit integers together. Each word must fit - * on 13 bits; source operands use 20 words, destination operand - * receives 40 words. All overlaps allowed. - * - * square20() computes the square of a 260-bit integer. Each word must - * fit on 13 bits; source operand uses 20 words, destination operand - * receives 40 words. All overlaps allowed. - */ - -#if BR_SLOW_MUL15 - -static void -mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * Two-level Karatsuba: turns a 20x20 multiplication into - * nine 5x5 multiplications. We use 13-bit words but do not - * propagate carries immediately, so words may expand: - * - * - First Karatsuba decomposition turns the 20x20 mul on - * 13-bit words into three 10x10 muls, two on 13-bit words - * and one on 14-bit words. - * - * - Second Karatsuba decomposition further splits these into: - * - * * four 5x5 muls on 13-bit words - * * four 5x5 muls on 14-bit words - * * one 5x5 mul on 15-bit words - * - * Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit - * or 15-bit words, respectively. - */ - uint32_t u[45], v[45], w[90]; - uint32_t cc; - int i; - -#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ - (dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \ - + (s2w)[5 * (s2_off) + 0]; \ - (dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \ - + (s2w)[5 * (s2_off) + 1]; \ - (dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \ - + (s2w)[5 * (s2_off) + 2]; \ - (dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \ - + (s2w)[5 * (s2_off) + 3]; \ - (dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \ - + (s2w)[5 * (s2_off) + 4]; \ - } while (0) - -#define ZADDT(dw, d_off, sw, s_off) do { \ - (dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \ - (dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \ - (dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \ - (dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \ - (dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \ - } while (0) - -#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \ - (dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \ - + (s2w)[5 * (s2_off) + 0]; \ - (dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \ - + (s2w)[5 * (s2_off) + 1]; \ - (dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \ - + (s2w)[5 * (s2_off) + 2]; \ - (dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \ - + (s2w)[5 * (s2_off) + 3]; \ - (dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \ - + (s2w)[5 * (s2_off) + 4]; \ - } while (0) - -#define CPR1(w, cprcc) do { \ - uint32_t cprz = (w) + cprcc; \ - (w) = cprz & 0x1FFF; \ - cprcc = cprz >> 13; \ - } while (0) - -#define CPR(dw, d_off) do { \ - uint32_t cprcc; \ - cprcc = 0; \ - CPR1((dw)[(d_off) + 0], cprcc); \ - CPR1((dw)[(d_off) + 1], cprcc); \ - CPR1((dw)[(d_off) + 2], cprcc); \ - CPR1((dw)[(d_off) + 3], cprcc); \ - CPR1((dw)[(d_off) + 4], cprcc); \ - CPR1((dw)[(d_off) + 5], cprcc); \ - CPR1((dw)[(d_off) + 6], cprcc); \ - CPR1((dw)[(d_off) + 7], cprcc); \ - CPR1((dw)[(d_off) + 8], cprcc); \ - (dw)[(d_off) + 9] = cprcc; \ - } while (0) - - memcpy(u, a, 20 * sizeof *a); - ZADD(u, 4, a, 0, a, 1); - ZADD(u, 5, a, 2, a, 3); - ZADD(u, 6, a, 0, a, 2); - ZADD(u, 7, a, 1, a, 3); - ZADD(u, 8, u, 6, u, 7); - - memcpy(v, b, 20 * sizeof *b); - ZADD(v, 4, b, 0, b, 1); - ZADD(v, 5, b, 2, b, 3); - ZADD(v, 6, b, 0, b, 2); - ZADD(v, 7, b, 1, b, 3); - ZADD(v, 8, v, 6, v, 7); - - /* - * Do the eight first 8x8 muls. Source words are at most 16382 - * each, so we can add product results together "as is" in 32-bit - * words. - */ - for (i = 0; i < 40; i += 5) { - w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]); - w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1]) - + MUL15(u[i + 1], v[i + 0]); - w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2]) - + MUL15(u[i + 1], v[i + 1]) - + MUL15(u[i + 2], v[i + 0]); - w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3]) - + MUL15(u[i + 1], v[i + 2]) - + MUL15(u[i + 2], v[i + 1]) - + MUL15(u[i + 3], v[i + 0]); - w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4]) - + MUL15(u[i + 1], v[i + 3]) - + MUL15(u[i + 2], v[i + 2]) - + MUL15(u[i + 3], v[i + 1]) - + MUL15(u[i + 4], v[i + 0]); - w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4]) - + MUL15(u[i + 2], v[i + 3]) - + MUL15(u[i + 3], v[i + 2]) - + MUL15(u[i + 4], v[i + 1]); - w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4]) - + MUL15(u[i + 3], v[i + 3]) - + MUL15(u[i + 4], v[i + 2]); - w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4]) - + MUL15(u[i + 4], v[i + 3]); - w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]); - w[(i << 1) + 9] = 0; - } - - /* - * For the 9th multiplication, source words are up to 32764, - * so we must do some carry propagation. If we add up to - * 4 products and the carry is no more than 524224, then the - * result fits in 32 bits, and the next carry will be no more - * than 524224 (because 4*(32764^2)+524224 < 8192*524225). - * - * We thus just skip one of the products in the middle word, - * then do a carry propagation (this reduces words to 13 bits - * each, except possibly the last, which may use up to 17 bits - * or so), then add the missing product. - */ - w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]); - w[80 + 1] = MUL15(u[40 + 0], v[40 + 1]) - + MUL15(u[40 + 1], v[40 + 0]); - w[80 + 2] = MUL15(u[40 + 0], v[40 + 2]) - + MUL15(u[40 + 1], v[40 + 1]) - + MUL15(u[40 + 2], v[40 + 0]); - w[80 + 3] = MUL15(u[40 + 0], v[40 + 3]) - + MUL15(u[40 + 1], v[40 + 2]) - + MUL15(u[40 + 2], v[40 + 1]) - + MUL15(u[40 + 3], v[40 + 0]); - w[80 + 4] = MUL15(u[40 + 0], v[40 + 4]) - + MUL15(u[40 + 1], v[40 + 3]) - + MUL15(u[40 + 2], v[40 + 2]) - + MUL15(u[40 + 3], v[40 + 1]); - /* + MUL15(u[40 + 4], v[40 + 0]) */ - w[80 + 5] = MUL15(u[40 + 1], v[40 + 4]) - + MUL15(u[40 + 2], v[40 + 3]) - + MUL15(u[40 + 3], v[40 + 2]) - + MUL15(u[40 + 4], v[40 + 1]); - w[80 + 6] = MUL15(u[40 + 2], v[40 + 4]) - + MUL15(u[40 + 3], v[40 + 3]) - + MUL15(u[40 + 4], v[40 + 2]); - w[80 + 7] = MUL15(u[40 + 3], v[40 + 4]) - + MUL15(u[40 + 4], v[40 + 3]); - w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]); - - CPR(w, 80); - - w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]); - - /* - * The products on 14-bit words in slots 6 and 7 yield values - * up to 5*(16382^2) each, and we need to subtract two such - * values from the higher word. We need the subtraction to fit - * in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit. - * However, 10*(16382^2) does not fit. So we must perform a - * bit of reduction here. - */ - CPR(w, 60); - CPR(w, 70); - - /* - * Recompose results. - */ - - /* 0..1*0..1 into 0..3 */ - ZSUB2F(w, 8, w, 0, w, 2); - ZSUB2F(w, 9, w, 1, w, 3); - ZADDT(w, 1, w, 8); - ZADDT(w, 2, w, 9); - - /* 2..3*2..3 into 4..7 */ - ZSUB2F(w, 10, w, 4, w, 6); - ZSUB2F(w, 11, w, 5, w, 7); - ZADDT(w, 5, w, 10); - ZADDT(w, 6, w, 11); - - /* (0..1+2..3)*(0..1+2..3) into 12..15 */ - ZSUB2F(w, 16, w, 12, w, 14); - ZSUB2F(w, 17, w, 13, w, 15); - ZADDT(w, 13, w, 16); - ZADDT(w, 14, w, 17); - - /* first-level recomposition */ - ZSUB2F(w, 12, w, 0, w, 4); - ZSUB2F(w, 13, w, 1, w, 5); - ZSUB2F(w, 14, w, 2, w, 6); - ZSUB2F(w, 15, w, 3, w, 7); - ZADDT(w, 2, w, 12); - ZADDT(w, 3, w, 13); - ZADDT(w, 4, w, 14); - ZADDT(w, 5, w, 15); - - /* - * Perform carry propagation to bring all words down to 13 bits. - */ - cc = norm13(d, w, 40); - d[39] += (cc << 13); - -#undef ZADD -#undef ZADDT -#undef ZSUB2F -#undef CPR1 -#undef CPR -} - -static inline void -square20(uint32_t *d, const uint32_t *a) -{ - mul20(d, a, a); -} - -#else - -static void -mul20(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[39]; - - t[ 0] = MUL15(a[ 0], b[ 0]); - t[ 1] = MUL15(a[ 0], b[ 1]) - + MUL15(a[ 1], b[ 0]); - t[ 2] = MUL15(a[ 0], b[ 2]) - + MUL15(a[ 1], b[ 1]) - + MUL15(a[ 2], b[ 0]); - t[ 3] = MUL15(a[ 0], b[ 3]) - + MUL15(a[ 1], b[ 2]) - + MUL15(a[ 2], b[ 1]) - + MUL15(a[ 3], b[ 0]); - t[ 4] = MUL15(a[ 0], b[ 4]) - + MUL15(a[ 1], b[ 3]) - + MUL15(a[ 2], b[ 2]) - + MUL15(a[ 3], b[ 1]) - + MUL15(a[ 4], b[ 0]); - t[ 5] = MUL15(a[ 0], b[ 5]) - + MUL15(a[ 1], b[ 4]) - + MUL15(a[ 2], b[ 3]) - + MUL15(a[ 3], b[ 2]) - + MUL15(a[ 4], b[ 1]) - + MUL15(a[ 5], b[ 0]); - t[ 6] = MUL15(a[ 0], b[ 6]) - + MUL15(a[ 1], b[ 5]) - + MUL15(a[ 2], b[ 4]) - + MUL15(a[ 3], b[ 3]) - + MUL15(a[ 4], b[ 2]) - + MUL15(a[ 5], b[ 1]) - + MUL15(a[ 6], b[ 0]); - t[ 7] = MUL15(a[ 0], b[ 7]) - + MUL15(a[ 1], b[ 6]) - + MUL15(a[ 2], b[ 5]) - + MUL15(a[ 3], b[ 4]) - + MUL15(a[ 4], b[ 3]) - + MUL15(a[ 5], b[ 2]) - + MUL15(a[ 6], b[ 1]) - + MUL15(a[ 7], b[ 0]); - t[ 8] = MUL15(a[ 0], b[ 8]) - + MUL15(a[ 1], b[ 7]) - + MUL15(a[ 2], b[ 6]) - + MUL15(a[ 3], b[ 5]) - + MUL15(a[ 4], b[ 4]) - + MUL15(a[ 5], b[ 3]) - + MUL15(a[ 6], b[ 2]) - + MUL15(a[ 7], b[ 1]) - + MUL15(a[ 8], b[ 0]); - t[ 9] = MUL15(a[ 0], b[ 9]) - + MUL15(a[ 1], b[ 8]) - + MUL15(a[ 2], b[ 7]) - + MUL15(a[ 3], b[ 6]) - + MUL15(a[ 4], b[ 5]) - + MUL15(a[ 5], b[ 4]) - + MUL15(a[ 6], b[ 3]) - + MUL15(a[ 7], b[ 2]) - + MUL15(a[ 8], b[ 1]) - + MUL15(a[ 9], b[ 0]); - t[10] = MUL15(a[ 0], b[10]) - + MUL15(a[ 1], b[ 9]) - + MUL15(a[ 2], b[ 8]) - + MUL15(a[ 3], b[ 7]) - + MUL15(a[ 4], b[ 6]) - + MUL15(a[ 5], b[ 5]) - + MUL15(a[ 6], b[ 4]) - + MUL15(a[ 7], b[ 3]) - + MUL15(a[ 8], b[ 2]) - + MUL15(a[ 9], b[ 1]) - + MUL15(a[10], b[ 0]); - t[11] = MUL15(a[ 0], b[11]) - + MUL15(a[ 1], b[10]) - + MUL15(a[ 2], b[ 9]) - + MUL15(a[ 3], b[ 8]) - + MUL15(a[ 4], b[ 7]) - + MUL15(a[ 5], b[ 6]) - + MUL15(a[ 6], b[ 5]) - + MUL15(a[ 7], b[ 4]) - + MUL15(a[ 8], b[ 3]) - + MUL15(a[ 9], b[ 2]) - + MUL15(a[10], b[ 1]) - + MUL15(a[11], b[ 0]); - t[12] = MUL15(a[ 0], b[12]) - + MUL15(a[ 1], b[11]) - + MUL15(a[ 2], b[10]) - + MUL15(a[ 3], b[ 9]) - + MUL15(a[ 4], b[ 8]) - + MUL15(a[ 5], b[ 7]) - + MUL15(a[ 6], b[ 6]) - + MUL15(a[ 7], b[ 5]) - + MUL15(a[ 8], b[ 4]) - + MUL15(a[ 9], b[ 3]) - + MUL15(a[10], b[ 2]) - + MUL15(a[11], b[ 1]) - + MUL15(a[12], b[ 0]); - t[13] = MUL15(a[ 0], b[13]) - + MUL15(a[ 1], b[12]) - + MUL15(a[ 2], b[11]) - + MUL15(a[ 3], b[10]) - + MUL15(a[ 4], b[ 9]) - + MUL15(a[ 5], b[ 8]) - + MUL15(a[ 6], b[ 7]) - + MUL15(a[ 7], b[ 6]) - + MUL15(a[ 8], b[ 5]) - + MUL15(a[ 9], b[ 4]) - + MUL15(a[10], b[ 3]) - + MUL15(a[11], b[ 2]) - + MUL15(a[12], b[ 1]) - + MUL15(a[13], b[ 0]); - t[14] = MUL15(a[ 0], b[14]) - + MUL15(a[ 1], b[13]) - + MUL15(a[ 2], b[12]) - + MUL15(a[ 3], b[11]) - + MUL15(a[ 4], b[10]) - + MUL15(a[ 5], b[ 9]) - + MUL15(a[ 6], b[ 8]) - + MUL15(a[ 7], b[ 7]) - + MUL15(a[ 8], b[ 6]) - + MUL15(a[ 9], b[ 5]) - + MUL15(a[10], b[ 4]) - + MUL15(a[11], b[ 3]) - + MUL15(a[12], b[ 2]) - + MUL15(a[13], b[ 1]) - + MUL15(a[14], b[ 0]); - t[15] = MUL15(a[ 0], b[15]) - + MUL15(a[ 1], b[14]) - + MUL15(a[ 2], b[13]) - + MUL15(a[ 3], b[12]) - + MUL15(a[ 4], b[11]) - + MUL15(a[ 5], b[10]) - + MUL15(a[ 6], b[ 9]) - + MUL15(a[ 7], b[ 8]) - + MUL15(a[ 8], b[ 7]) - + MUL15(a[ 9], b[ 6]) - + MUL15(a[10], b[ 5]) - + MUL15(a[11], b[ 4]) - + MUL15(a[12], b[ 3]) - + MUL15(a[13], b[ 2]) - + MUL15(a[14], b[ 1]) - + MUL15(a[15], b[ 0]); - t[16] = MUL15(a[ 0], b[16]) - + MUL15(a[ 1], b[15]) - + MUL15(a[ 2], b[14]) - + MUL15(a[ 3], b[13]) - + MUL15(a[ 4], b[12]) - + MUL15(a[ 5], b[11]) - + MUL15(a[ 6], b[10]) - + MUL15(a[ 7], b[ 9]) - + MUL15(a[ 8], b[ 8]) - + MUL15(a[ 9], b[ 7]) - + MUL15(a[10], b[ 6]) - + MUL15(a[11], b[ 5]) - + MUL15(a[12], b[ 4]) - + MUL15(a[13], b[ 3]) - + MUL15(a[14], b[ 2]) - + MUL15(a[15], b[ 1]) - + MUL15(a[16], b[ 0]); - t[17] = MUL15(a[ 0], b[17]) - + MUL15(a[ 1], b[16]) - + MUL15(a[ 2], b[15]) - + MUL15(a[ 3], b[14]) - + MUL15(a[ 4], b[13]) - + MUL15(a[ 5], b[12]) - + MUL15(a[ 6], b[11]) - + MUL15(a[ 7], b[10]) - + MUL15(a[ 8], b[ 9]) - + MUL15(a[ 9], b[ 8]) - + MUL15(a[10], b[ 7]) - + MUL15(a[11], b[ 6]) - + MUL15(a[12], b[ 5]) - + MUL15(a[13], b[ 4]) - + MUL15(a[14], b[ 3]) - + MUL15(a[15], b[ 2]) - + MUL15(a[16], b[ 1]) - + MUL15(a[17], b[ 0]); - t[18] = MUL15(a[ 0], b[18]) - + MUL15(a[ 1], b[17]) - + MUL15(a[ 2], b[16]) - + MUL15(a[ 3], b[15]) - + MUL15(a[ 4], b[14]) - + MUL15(a[ 5], b[13]) - + MUL15(a[ 6], b[12]) - + MUL15(a[ 7], b[11]) - + MUL15(a[ 8], b[10]) - + MUL15(a[ 9], b[ 9]) - + MUL15(a[10], b[ 8]) - + MUL15(a[11], b[ 7]) - + MUL15(a[12], b[ 6]) - + MUL15(a[13], b[ 5]) - + MUL15(a[14], b[ 4]) - + MUL15(a[15], b[ 3]) - + MUL15(a[16], b[ 2]) - + MUL15(a[17], b[ 1]) - + MUL15(a[18], b[ 0]); - t[19] = MUL15(a[ 0], b[19]) - + MUL15(a[ 1], b[18]) - + MUL15(a[ 2], b[17]) - + MUL15(a[ 3], b[16]) - + MUL15(a[ 4], b[15]) - + MUL15(a[ 5], b[14]) - + MUL15(a[ 6], b[13]) - + MUL15(a[ 7], b[12]) - + MUL15(a[ 8], b[11]) - + MUL15(a[ 9], b[10]) - + MUL15(a[10], b[ 9]) - + MUL15(a[11], b[ 8]) - + MUL15(a[12], b[ 7]) - + MUL15(a[13], b[ 6]) - + MUL15(a[14], b[ 5]) - + MUL15(a[15], b[ 4]) - + MUL15(a[16], b[ 3]) - + MUL15(a[17], b[ 2]) - + MUL15(a[18], b[ 1]) - + MUL15(a[19], b[ 0]); - t[20] = MUL15(a[ 1], b[19]) - + MUL15(a[ 2], b[18]) - + MUL15(a[ 3], b[17]) - + MUL15(a[ 4], b[16]) - + MUL15(a[ 5], b[15]) - + MUL15(a[ 6], b[14]) - + MUL15(a[ 7], b[13]) - + MUL15(a[ 8], b[12]) - + MUL15(a[ 9], b[11]) - + MUL15(a[10], b[10]) - + MUL15(a[11], b[ 9]) - + MUL15(a[12], b[ 8]) - + MUL15(a[13], b[ 7]) - + MUL15(a[14], b[ 6]) - + MUL15(a[15], b[ 5]) - + MUL15(a[16], b[ 4]) - + MUL15(a[17], b[ 3]) - + MUL15(a[18], b[ 2]) - + MUL15(a[19], b[ 1]); - t[21] = MUL15(a[ 2], b[19]) - + MUL15(a[ 3], b[18]) - + MUL15(a[ 4], b[17]) - + MUL15(a[ 5], b[16]) - + MUL15(a[ 6], b[15]) - + MUL15(a[ 7], b[14]) - + MUL15(a[ 8], b[13]) - + MUL15(a[ 9], b[12]) - + MUL15(a[10], b[11]) - + MUL15(a[11], b[10]) - + MUL15(a[12], b[ 9]) - + MUL15(a[13], b[ 8]) - + MUL15(a[14], b[ 7]) - + MUL15(a[15], b[ 6]) - + MUL15(a[16], b[ 5]) - + MUL15(a[17], b[ 4]) - + MUL15(a[18], b[ 3]) - + MUL15(a[19], b[ 2]); - t[22] = MUL15(a[ 3], b[19]) - + MUL15(a[ 4], b[18]) - + MUL15(a[ 5], b[17]) - + MUL15(a[ 6], b[16]) - + MUL15(a[ 7], b[15]) - + MUL15(a[ 8], b[14]) - + MUL15(a[ 9], b[13]) - + MUL15(a[10], b[12]) - + MUL15(a[11], b[11]) - + MUL15(a[12], b[10]) - + MUL15(a[13], b[ 9]) - + MUL15(a[14], b[ 8]) - + MUL15(a[15], b[ 7]) - + MUL15(a[16], b[ 6]) - + MUL15(a[17], b[ 5]) - + MUL15(a[18], b[ 4]) - + MUL15(a[19], b[ 3]); - t[23] = MUL15(a[ 4], b[19]) - + MUL15(a[ 5], b[18]) - + MUL15(a[ 6], b[17]) - + MUL15(a[ 7], b[16]) - + MUL15(a[ 8], b[15]) - + MUL15(a[ 9], b[14]) - + MUL15(a[10], b[13]) - + MUL15(a[11], b[12]) - + MUL15(a[12], b[11]) - + MUL15(a[13], b[10]) - + MUL15(a[14], b[ 9]) - + MUL15(a[15], b[ 8]) - + MUL15(a[16], b[ 7]) - + MUL15(a[17], b[ 6]) - + MUL15(a[18], b[ 5]) - + MUL15(a[19], b[ 4]); - t[24] = MUL15(a[ 5], b[19]) - + MUL15(a[ 6], b[18]) - + MUL15(a[ 7], b[17]) - + MUL15(a[ 8], b[16]) - + MUL15(a[ 9], b[15]) - + MUL15(a[10], b[14]) - + MUL15(a[11], b[13]) - + MUL15(a[12], b[12]) - + MUL15(a[13], b[11]) - + MUL15(a[14], b[10]) - + MUL15(a[15], b[ 9]) - + MUL15(a[16], b[ 8]) - + MUL15(a[17], b[ 7]) - + MUL15(a[18], b[ 6]) - + MUL15(a[19], b[ 5]); - t[25] = MUL15(a[ 6], b[19]) - + MUL15(a[ 7], b[18]) - + MUL15(a[ 8], b[17]) - + MUL15(a[ 9], b[16]) - + MUL15(a[10], b[15]) - + MUL15(a[11], b[14]) - + MUL15(a[12], b[13]) - + MUL15(a[13], b[12]) - + MUL15(a[14], b[11]) - + MUL15(a[15], b[10]) - + MUL15(a[16], b[ 9]) - + MUL15(a[17], b[ 8]) - + MUL15(a[18], b[ 7]) - + MUL15(a[19], b[ 6]); - t[26] = MUL15(a[ 7], b[19]) - + MUL15(a[ 8], b[18]) - + MUL15(a[ 9], b[17]) - + MUL15(a[10], b[16]) - + MUL15(a[11], b[15]) - + MUL15(a[12], b[14]) - + MUL15(a[13], b[13]) - + MUL15(a[14], b[12]) - + MUL15(a[15], b[11]) - + MUL15(a[16], b[10]) - + MUL15(a[17], b[ 9]) - + MUL15(a[18], b[ 8]) - + MUL15(a[19], b[ 7]); - t[27] = MUL15(a[ 8], b[19]) - + MUL15(a[ 9], b[18]) - + MUL15(a[10], b[17]) - + MUL15(a[11], b[16]) - + MUL15(a[12], b[15]) - + MUL15(a[13], b[14]) - + MUL15(a[14], b[13]) - + MUL15(a[15], b[12]) - + MUL15(a[16], b[11]) - + MUL15(a[17], b[10]) - + MUL15(a[18], b[ 9]) - + MUL15(a[19], b[ 8]); - t[28] = MUL15(a[ 9], b[19]) - + MUL15(a[10], b[18]) - + MUL15(a[11], b[17]) - + MUL15(a[12], b[16]) - + MUL15(a[13], b[15]) - + MUL15(a[14], b[14]) - + MUL15(a[15], b[13]) - + MUL15(a[16], b[12]) - + MUL15(a[17], b[11]) - + MUL15(a[18], b[10]) - + MUL15(a[19], b[ 9]); - t[29] = MUL15(a[10], b[19]) - + MUL15(a[11], b[18]) - + MUL15(a[12], b[17]) - + MUL15(a[13], b[16]) - + MUL15(a[14], b[15]) - + MUL15(a[15], b[14]) - + MUL15(a[16], b[13]) - + MUL15(a[17], b[12]) - + MUL15(a[18], b[11]) - + MUL15(a[19], b[10]); - t[30] = MUL15(a[11], b[19]) - + MUL15(a[12], b[18]) - + MUL15(a[13], b[17]) - + MUL15(a[14], b[16]) - + MUL15(a[15], b[15]) - + MUL15(a[16], b[14]) - + MUL15(a[17], b[13]) - + MUL15(a[18], b[12]) - + MUL15(a[19], b[11]); - t[31] = MUL15(a[12], b[19]) - + MUL15(a[13], b[18]) - + MUL15(a[14], b[17]) - + MUL15(a[15], b[16]) - + MUL15(a[16], b[15]) - + MUL15(a[17], b[14]) - + MUL15(a[18], b[13]) - + MUL15(a[19], b[12]); - t[32] = MUL15(a[13], b[19]) - + MUL15(a[14], b[18]) - + MUL15(a[15], b[17]) - + MUL15(a[16], b[16]) - + MUL15(a[17], b[15]) - + MUL15(a[18], b[14]) - + MUL15(a[19], b[13]); - t[33] = MUL15(a[14], b[19]) - + MUL15(a[15], b[18]) - + MUL15(a[16], b[17]) - + MUL15(a[17], b[16]) - + MUL15(a[18], b[15]) - + MUL15(a[19], b[14]); - t[34] = MUL15(a[15], b[19]) - + MUL15(a[16], b[18]) - + MUL15(a[17], b[17]) - + MUL15(a[18], b[16]) - + MUL15(a[19], b[15]); - t[35] = MUL15(a[16], b[19]) - + MUL15(a[17], b[18]) - + MUL15(a[18], b[17]) - + MUL15(a[19], b[16]); - t[36] = MUL15(a[17], b[19]) - + MUL15(a[18], b[18]) - + MUL15(a[19], b[17]); - t[37] = MUL15(a[18], b[19]) - + MUL15(a[19], b[18]); - t[38] = MUL15(a[19], b[19]); - d[39] = norm13(d, t, 39); -} - -static void -square20(uint32_t *d, const uint32_t *a) -{ - uint32_t t[39]; - - t[ 0] = MUL15(a[ 0], a[ 0]); - t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1); - t[ 2] = MUL15(a[ 1], a[ 1]) - + ((MUL15(a[ 0], a[ 2])) << 1); - t[ 3] = ((MUL15(a[ 0], a[ 3]) - + MUL15(a[ 1], a[ 2])) << 1); - t[ 4] = MUL15(a[ 2], a[ 2]) - + ((MUL15(a[ 0], a[ 4]) - + MUL15(a[ 1], a[ 3])) << 1); - t[ 5] = ((MUL15(a[ 0], a[ 5]) - + MUL15(a[ 1], a[ 4]) - + MUL15(a[ 2], a[ 3])) << 1); - t[ 6] = MUL15(a[ 3], a[ 3]) - + ((MUL15(a[ 0], a[ 6]) - + MUL15(a[ 1], a[ 5]) - + MUL15(a[ 2], a[ 4])) << 1); - t[ 7] = ((MUL15(a[ 0], a[ 7]) - + MUL15(a[ 1], a[ 6]) - + MUL15(a[ 2], a[ 5]) - + MUL15(a[ 3], a[ 4])) << 1); - t[ 8] = MUL15(a[ 4], a[ 4]) - + ((MUL15(a[ 0], a[ 8]) - + MUL15(a[ 1], a[ 7]) - + MUL15(a[ 2], a[ 6]) - + MUL15(a[ 3], a[ 5])) << 1); - t[ 9] = ((MUL15(a[ 0], a[ 9]) - + MUL15(a[ 1], a[ 8]) - + MUL15(a[ 2], a[ 7]) - + MUL15(a[ 3], a[ 6]) - + MUL15(a[ 4], a[ 5])) << 1); - t[10] = MUL15(a[ 5], a[ 5]) - + ((MUL15(a[ 0], a[10]) - + MUL15(a[ 1], a[ 9]) - + MUL15(a[ 2], a[ 8]) - + MUL15(a[ 3], a[ 7]) - + MUL15(a[ 4], a[ 6])) << 1); - t[11] = ((MUL15(a[ 0], a[11]) - + MUL15(a[ 1], a[10]) - + MUL15(a[ 2], a[ 9]) - + MUL15(a[ 3], a[ 8]) - + MUL15(a[ 4], a[ 7]) - + MUL15(a[ 5], a[ 6])) << 1); - t[12] = MUL15(a[ 6], a[ 6]) - + ((MUL15(a[ 0], a[12]) - + MUL15(a[ 1], a[11]) - + MUL15(a[ 2], a[10]) - + MUL15(a[ 3], a[ 9]) - + MUL15(a[ 4], a[ 8]) - + MUL15(a[ 5], a[ 7])) << 1); - t[13] = ((MUL15(a[ 0], a[13]) - + MUL15(a[ 1], a[12]) - + MUL15(a[ 2], a[11]) - + MUL15(a[ 3], a[10]) - + MUL15(a[ 4], a[ 9]) - + MUL15(a[ 5], a[ 8]) - + MUL15(a[ 6], a[ 7])) << 1); - t[14] = MUL15(a[ 7], a[ 7]) - + ((MUL15(a[ 0], a[14]) - + MUL15(a[ 1], a[13]) - + MUL15(a[ 2], a[12]) - + MUL15(a[ 3], a[11]) - + MUL15(a[ 4], a[10]) - + MUL15(a[ 5], a[ 9]) - + MUL15(a[ 6], a[ 8])) << 1); - t[15] = ((MUL15(a[ 0], a[15]) - + MUL15(a[ 1], a[14]) - + MUL15(a[ 2], a[13]) - + MUL15(a[ 3], a[12]) - + MUL15(a[ 4], a[11]) - + MUL15(a[ 5], a[10]) - + MUL15(a[ 6], a[ 9]) - + MUL15(a[ 7], a[ 8])) << 1); - t[16] = MUL15(a[ 8], a[ 8]) - + ((MUL15(a[ 0], a[16]) - + MUL15(a[ 1], a[15]) - + MUL15(a[ 2], a[14]) - + MUL15(a[ 3], a[13]) - + MUL15(a[ 4], a[12]) - + MUL15(a[ 5], a[11]) - + MUL15(a[ 6], a[10]) - + MUL15(a[ 7], a[ 9])) << 1); - t[17] = ((MUL15(a[ 0], a[17]) - + MUL15(a[ 1], a[16]) - + MUL15(a[ 2], a[15]) - + MUL15(a[ 3], a[14]) - + MUL15(a[ 4], a[13]) - + MUL15(a[ 5], a[12]) - + MUL15(a[ 6], a[11]) - + MUL15(a[ 7], a[10]) - + MUL15(a[ 8], a[ 9])) << 1); - t[18] = MUL15(a[ 9], a[ 9]) - + ((MUL15(a[ 0], a[18]) - + MUL15(a[ 1], a[17]) - + MUL15(a[ 2], a[16]) - + MUL15(a[ 3], a[15]) - + MUL15(a[ 4], a[14]) - + MUL15(a[ 5], a[13]) - + MUL15(a[ 6], a[12]) - + MUL15(a[ 7], a[11]) - + MUL15(a[ 8], a[10])) << 1); - t[19] = ((MUL15(a[ 0], a[19]) - + MUL15(a[ 1], a[18]) - + MUL15(a[ 2], a[17]) - + MUL15(a[ 3], a[16]) - + MUL15(a[ 4], a[15]) - + MUL15(a[ 5], a[14]) - + MUL15(a[ 6], a[13]) - + MUL15(a[ 7], a[12]) - + MUL15(a[ 8], a[11]) - + MUL15(a[ 9], a[10])) << 1); - t[20] = MUL15(a[10], a[10]) - + ((MUL15(a[ 1], a[19]) - + MUL15(a[ 2], a[18]) - + MUL15(a[ 3], a[17]) - + MUL15(a[ 4], a[16]) - + MUL15(a[ 5], a[15]) - + MUL15(a[ 6], a[14]) - + MUL15(a[ 7], a[13]) - + MUL15(a[ 8], a[12]) - + MUL15(a[ 9], a[11])) << 1); - t[21] = ((MUL15(a[ 2], a[19]) - + MUL15(a[ 3], a[18]) - + MUL15(a[ 4], a[17]) - + MUL15(a[ 5], a[16]) - + MUL15(a[ 6], a[15]) - + MUL15(a[ 7], a[14]) - + MUL15(a[ 8], a[13]) - + MUL15(a[ 9], a[12]) - + MUL15(a[10], a[11])) << 1); - t[22] = MUL15(a[11], a[11]) - + ((MUL15(a[ 3], a[19]) - + MUL15(a[ 4], a[18]) - + MUL15(a[ 5], a[17]) - + MUL15(a[ 6], a[16]) - + MUL15(a[ 7], a[15]) - + MUL15(a[ 8], a[14]) - + MUL15(a[ 9], a[13]) - + MUL15(a[10], a[12])) << 1); - t[23] = ((MUL15(a[ 4], a[19]) - + MUL15(a[ 5], a[18]) - + MUL15(a[ 6], a[17]) - + MUL15(a[ 7], a[16]) - + MUL15(a[ 8], a[15]) - + MUL15(a[ 9], a[14]) - + MUL15(a[10], a[13]) - + MUL15(a[11], a[12])) << 1); - t[24] = MUL15(a[12], a[12]) - + ((MUL15(a[ 5], a[19]) - + MUL15(a[ 6], a[18]) - + MUL15(a[ 7], a[17]) - + MUL15(a[ 8], a[16]) - + MUL15(a[ 9], a[15]) - + MUL15(a[10], a[14]) - + MUL15(a[11], a[13])) << 1); - t[25] = ((MUL15(a[ 6], a[19]) - + MUL15(a[ 7], a[18]) - + MUL15(a[ 8], a[17]) - + MUL15(a[ 9], a[16]) - + MUL15(a[10], a[15]) - + MUL15(a[11], a[14]) - + MUL15(a[12], a[13])) << 1); - t[26] = MUL15(a[13], a[13]) - + ((MUL15(a[ 7], a[19]) - + MUL15(a[ 8], a[18]) - + MUL15(a[ 9], a[17]) - + MUL15(a[10], a[16]) - + MUL15(a[11], a[15]) - + MUL15(a[12], a[14])) << 1); - t[27] = ((MUL15(a[ 8], a[19]) - + MUL15(a[ 9], a[18]) - + MUL15(a[10], a[17]) - + MUL15(a[11], a[16]) - + MUL15(a[12], a[15]) - + MUL15(a[13], a[14])) << 1); - t[28] = MUL15(a[14], a[14]) - + ((MUL15(a[ 9], a[19]) - + MUL15(a[10], a[18]) - + MUL15(a[11], a[17]) - + MUL15(a[12], a[16]) - + MUL15(a[13], a[15])) << 1); - t[29] = ((MUL15(a[10], a[19]) - + MUL15(a[11], a[18]) - + MUL15(a[12], a[17]) - + MUL15(a[13], a[16]) - + MUL15(a[14], a[15])) << 1); - t[30] = MUL15(a[15], a[15]) - + ((MUL15(a[11], a[19]) - + MUL15(a[12], a[18]) - + MUL15(a[13], a[17]) - + MUL15(a[14], a[16])) << 1); - t[31] = ((MUL15(a[12], a[19]) - + MUL15(a[13], a[18]) - + MUL15(a[14], a[17]) - + MUL15(a[15], a[16])) << 1); - t[32] = MUL15(a[16], a[16]) - + ((MUL15(a[13], a[19]) - + MUL15(a[14], a[18]) - + MUL15(a[15], a[17])) << 1); - t[33] = ((MUL15(a[14], a[19]) - + MUL15(a[15], a[18]) - + MUL15(a[16], a[17])) << 1); - t[34] = MUL15(a[17], a[17]) - + ((MUL15(a[15], a[19]) - + MUL15(a[16], a[18])) << 1); - t[35] = ((MUL15(a[16], a[19]) - + MUL15(a[17], a[18])) << 1); - t[36] = MUL15(a[18], a[18]) - + ((MUL15(a[17], a[19])) << 1); - t[37] = ((MUL15(a[18], a[19])) << 1); - t[38] = MUL15(a[19], a[19]); - d[39] = norm13(d, t, 39); -} - -#endif - -/* - * Modulus for field F256 (field for point coordinates in curve P-256). - */ -static const uint32_t F256[] = { - 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x001F, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0000, - 0x0000, 0x1FF8, 0x1FFF, 0x01FF -}; - -/* - * The 'b' curve equation coefficient for P-256. - */ -static const uint32_t P256_B[] = { - 0x004B, 0x1E93, 0x0F89, 0x1C78, 0x03BC, 0x187B, 0x114E, 0x1619, - 0x1D06, 0x0328, 0x01AF, 0x0D31, 0x1557, 0x15DE, 0x1ECF, 0x127C, - 0x0A3A, 0x0EC5, 0x118D, 0x00B5 -}; - -/* - * Perform a "short reduction" in field F256 (field for curve P-256). - * The source value should be less than 262 bits; on output, it will - * be at most 257 bits, and less than twice the modulus. - */ -static void -reduce_f256(uint32_t *d) -{ - uint32_t x; - - x = d[19] >> 9; - d[19] &= 0x01FF; - d[17] += x << 3; - d[14] -= x << 10; - d[7] -= x << 5; - d[0] += x; - norm13(d, d, 20); -} - -/* - * Perform a "final reduction" in field F256 (field for curve P-256). - * The source value must be less than twice the modulus. If the value - * is not lower than the modulus, then the modulus is subtracted and - * this function returns 1; otherwise, it leaves it untouched and it - * returns 0. - */ -static uint32_t -reduce_final_f256(uint32_t *d) -{ - uint32_t t[20]; - uint32_t cc; - int i; - - memcpy(t, d, sizeof t); - cc = 0; - for (i = 0; i < 20; i ++) { - uint32_t w; - - w = t[i] - F256[i] - cc; - cc = w >> 31; - t[i] = w & 0x1FFF; - } - cc ^= 1; - CCOPY(cc, d, t, sizeof t); - return cc; -} - -/* - * Perform a multiplication of two integers modulo - * 2^256-2^224+2^192+2^96-1 (for NIST curve P-256). Operands are arrays - * of 20 words, each containing 13 bits of data, in little-endian order. - * On input, upper word may be up to 13 bits (hence value up to 2^260-1); - * on output, value fits on 257 bits and is lower than twice the modulus. - */ -static void -mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[40], cc; - int i; - - /* - * Compute raw multiplication. All result words fit in 13 bits - * each. - */ - mul20(t, a, b); - - /* - * Modular reduction: each high word in added/subtracted where - * necessary. - * - * The modulus is: - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 - * Therefore: - * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p - * - * For a word x at bit offset n (n >= 256), we have: - * x*2^n = x*2^(n-32) - x*2^(n-64) - * - x*2^(n - 160) + x*2^(n-256) mod p - * - * Thus, we can nullify the high word if we reinject it at some - * proper emplacements. - */ - for (i = 39; i >= 20; i --) { - uint32_t x; - - x = t[i]; - t[i - 2] += ARSH(x, 6); - t[i - 3] += (x << 7) & 0x1FFF; - t[i - 4] -= ARSH(x, 12); - t[i - 5] -= (x << 1) & 0x1FFF; - t[i - 12] -= ARSH(x, 4); - t[i - 13] -= (x << 9) & 0x1FFF; - t[i - 19] += ARSH(x, 9); - t[i - 20] += (x << 4) & 0x1FFF; - } - - /* - * Propagate carries. This is a signed propagation, and the - * result may be negative. The loop above may enlarge values, - * but not two much: worst case is the chain involving t[i - 3], - * in which a value may be added to itself up to 7 times. Since - * starting values are 13-bit each, all words fit on 20 bits - * (21 to account for the sign bit). - */ - cc = norm13(t, t, 20); - - /* - * Perform modular reduction again for the bits beyond 256 (the carry - * and the bits 256..259). Since the largest shift below is by 10 - * bits, and the values fit on 21 bits, values fit in 32-bit words, - * thereby allowing injecting full word values. - */ - cc = (cc << 4) | (t[19] >> 9); - t[19] &= 0x01FF; - t[17] += cc << 3; - t[14] -= cc << 10; - t[7] -= cc << 5; - t[0] += cc; - - /* - * If the carry is negative, then after carry propagation, we may - * end up with a value which is negative, and we don't want that. - * Thus, in that case, we add the modulus. Note that the subtraction - * result, when the carry is negative, is always smaller than the - * modulus, so the extra addition will not make the value exceed - * twice the modulus. - */ - cc >>= 31; - t[0] -= cc; - t[7] += cc << 5; - t[14] += cc << 10; - t[17] -= cc << 3; - t[19] += cc << 9; - - norm13(d, t, 20); -} - -/* - * Square an integer modulo 2^256-2^224+2^192+2^96-1 (for NIST curve - * P-256). Operand is an array of 20 words, each containing 13 bits of - * data, in little-endian order. On input, upper word may be up to 13 - * bits (hence value up to 2^260-1); on output, value fits on 257 bits - * and is lower than twice the modulus. - */ -static void -square_f256(uint32_t *d, const uint32_t *a) -{ - uint32_t t[40], cc; - int i; - - /* - * Compute raw square. All result words fit in 13 bits each. - */ - square20(t, a); - - /* - * Modular reduction: each high word in added/subtracted where - * necessary. - * - * The modulus is: - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 - * Therefore: - * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p - * - * For a word x at bit offset n (n >= 256), we have: - * x*2^n = x*2^(n-32) - x*2^(n-64) - * - x*2^(n - 160) + x*2^(n-256) mod p - * - * Thus, we can nullify the high word if we reinject it at some - * proper emplacements. - */ - for (i = 39; i >= 20; i --) { - uint32_t x; - - x = t[i]; - t[i - 2] += ARSH(x, 6); - t[i - 3] += (x << 7) & 0x1FFF; - t[i - 4] -= ARSH(x, 12); - t[i - 5] -= (x << 1) & 0x1FFF; - t[i - 12] -= ARSH(x, 4); - t[i - 13] -= (x << 9) & 0x1FFF; - t[i - 19] += ARSH(x, 9); - t[i - 20] += (x << 4) & 0x1FFF; - } - - /* - * Propagate carries. This is a signed propagation, and the - * result may be negative. The loop above may enlarge values, - * but not two much: worst case is the chain involving t[i - 3], - * in which a value may be added to itself up to 7 times. Since - * starting values are 13-bit each, all words fit on 20 bits - * (21 to account for the sign bit). - */ - cc = norm13(t, t, 20); - - /* - * Perform modular reduction again for the bits beyond 256 (the carry - * and the bits 256..259). Since the largest shift below is by 10 - * bits, and the values fit on 21 bits, values fit in 32-bit words, - * thereby allowing injecting full word values. - */ - cc = (cc << 4) | (t[19] >> 9); - t[19] &= 0x01FF; - t[17] += cc << 3; - t[14] -= cc << 10; - t[7] -= cc << 5; - t[0] += cc; - - /* - * If the carry is negative, then after carry propagation, we may - * end up with a value which is negative, and we don't want that. - * Thus, in that case, we add the modulus. Note that the subtraction - * result, when the carry is negative, is always smaller than the - * modulus, so the extra addition will not make the value exceed - * twice the modulus. - */ - cc >>= 31; - t[0] -= cc; - t[7] += cc << 5; - t[14] += cc << 10; - t[17] -= cc << 3; - t[19] += cc << 9; - - norm13(d, t, 20); -} - -/* - * Jacobian coordinates for a point in P-256: affine coordinates (X,Y) - * are such that: - * X = x / z^2 - * Y = y / z^3 - * For the point at infinity, z = 0. - * Each point thus admits many possible representations. - * - * Coordinates are represented in arrays of 32-bit integers, each holding - * 13 bits of data. Values may also be slightly greater than the modulus, - * but they will always be lower than twice the modulus. - */ -typedef struct { - uint32_t x[20]; - uint32_t y[20]; - uint32_t z[20]; -} p256_jacobian; - -/* - * Convert a point to affine coordinates: - * - If the point is the point at infinity, then all three coordinates - * are set to 0. - * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y' - * coordinates are the 'X' and 'Y' affine coordinates. - * The coordinates are guaranteed to be lower than the modulus. - */ -static void -p256_to_affine(p256_jacobian *P) -{ - uint32_t t1[20], t2[20]; - int i; - - /* - * Invert z with a modular exponentiation: the modulus is - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is - * p-2. Exponent bit pattern (from high to low) is: - * - 32 bits of value 1 - * - 31 bits of value 0 - * - 1 bit of value 1 - * - 96 bits of value 0 - * - 94 bits of value 1 - * - 1 bit of value 0 - * - 1 bit of value 1 - * Thus, we precompute z^(2^31-1) to speed things up. - * - * If z = 0 (point at infinity) then the modular exponentiation - * will yield 0, which leads to the expected result (all three - * coordinates set to 0). - */ - - /* - * A simple square-and-multiply for z^(2^31-1). We could save about - * two dozen multiplications here with an addition chain, but - * this would require a bit more code, and extra stack buffers. - */ - memcpy(t1, P->z, sizeof P->z); - for (i = 0; i < 30; i ++) { - square_f256(t1, t1); - mul_f256(t1, t1, P->z); - } - - /* - * Square-and-multiply. Apart from the squarings, we have a few - * multiplications to set bits to 1; we multiply by the original z - * for setting 1 bit, and by t1 for setting 31 bits. - */ - memcpy(t2, P->z, sizeof P->z); - for (i = 1; i < 256; i ++) { - square_f256(t2, t2); - switch (i) { - case 31: - case 190: - case 221: - case 252: - mul_f256(t2, t2, t1); - break; - case 63: - case 253: - case 255: - mul_f256(t2, t2, P->z); - break; - } - } - - /* - * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3. - */ - mul_f256(t1, t2, t2); - mul_f256(P->x, t1, P->x); - mul_f256(t1, t1, t2); - mul_f256(P->y, t1, P->y); - reduce_final_f256(P->x); - reduce_final_f256(P->y); - - /* - * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise - * this will set z to 1. - */ - mul_f256(P->z, P->z, t2); - reduce_final_f256(P->z); -} - -/* - * Double a point in P-256. This function works for all valid points, - * including the point at infinity. - */ -static void -p256_double(p256_jacobian *Q) -{ - /* - * Doubling formulas are: - * - * s = 4*x*y^2 - * m = 3*(x + z^2)*(x - z^2) - * x' = m^2 - 2*s - * y' = m*(s - x') - 8*y^4 - * z' = 2*y*z - * - * These formulas work for all points, including points of order 2 - * and points at infinity: - * - If y = 0 then z' = 0. But there is no such point in P-256 - * anyway. - * - If z = 0 then z' = 0. - */ - uint32_t t1[20], t2[20], t3[20], t4[20]; - int i; - - /* - * Compute z^2 in t1. - */ - square_f256(t1, Q->z); - - /* - * Compute x-z^2 in t2 and x+z^2 in t1. - */ - for (i = 0; i < 20; i ++) { - t2[i] = (F256[i] << 1) + Q->x[i] - t1[i]; - t1[i] += Q->x[i]; - } - norm13(t1, t1, 20); - norm13(t2, t2, 20); - - /* - * Compute 3*(x+z^2)*(x-z^2) in t1. - */ - mul_f256(t3, t1, t2); - for (i = 0; i < 20; i ++) { - t1[i] = MUL15(3, t3[i]); - } - norm13(t1, t1, 20); - - /* - * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). - */ - square_f256(t3, Q->y); - for (i = 0; i < 20; i ++) { - t3[i] <<= 1; - } - norm13(t3, t3, 20); - mul_f256(t2, Q->x, t3); - for (i = 0; i < 20; i ++) { - t2[i] <<= 1; - } - norm13(t2, t2, 20); - reduce_f256(t2); - - /* - * Compute x' = m^2 - 2*s. - */ - square_f256(Q->x, t1); - for (i = 0; i < 20; i ++) { - Q->x[i] += (F256[i] << 2) - (t2[i] << 1); - } - norm13(Q->x, Q->x, 20); - reduce_f256(Q->x); - - /* - * Compute z' = 2*y*z. - */ - mul_f256(t4, Q->y, Q->z); - for (i = 0; i < 20; i ++) { - Q->z[i] = t4[i] << 1; - } - norm13(Q->z, Q->z, 20); - reduce_f256(Q->z); - - /* - * Compute y' = m*(s - x') - 8*y^4. Note that we already have - * 2*y^2 in t3. - */ - for (i = 0; i < 20; i ++) { - t2[i] += (F256[i] << 1) - Q->x[i]; - } - norm13(t2, t2, 20); - mul_f256(Q->y, t1, t2); - square_f256(t4, t3); - for (i = 0; i < 20; i ++) { - Q->y[i] += (F256[i] << 2) - (t4[i] << 1); - } - norm13(Q->y, Q->y, 20); - reduce_f256(Q->y); -} - -/* - * Add point P2 to point P1. - * - * This function computes the wrong result in the following cases: - * - * - If P1 == 0 but P2 != 0 - * - If P1 != 0 but P2 == 0 - * - If P1 == P2 - * - * In all three cases, P1 is set to the point at infinity. - * - * Returned value is 0 if one of the following occurs: - * - * - P1 and P2 have the same Y coordinate - * - P1 == 0 and P2 == 0 - * - The Y coordinate of one of the points is 0 and the other point is - * the point at infinity. - * - * The third case cannot actually happen with valid points, since a point - * with Y == 0 is a point of order 2, and there is no point of order 2 on - * curve P-256. - * - * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller - * can apply the following: - * - * - If the result is not the point at infinity, then it is correct. - * - Otherwise, if the returned value is 1, then this is a case of - * P1+P2 == 0, so the result is indeed the point at infinity. - * - Otherwise, P1 == P2, so a "double" operation should have been - * performed. - */ -static uint32_t -p256_add(p256_jacobian *P1, const p256_jacobian *P2) -{ - /* - * Addtions formulas are: - * - * u1 = x1 * z2^2 - * u2 = x2 * z1^2 - * s1 = y1 * z2^3 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 * z2 - */ - uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20]; - uint32_t ret; - int i; - - /* - * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). - */ - square_f256(t3, P2->z); - mul_f256(t1, P1->x, t3); - mul_f256(t4, P2->z, t3); - mul_f256(t3, P1->y, t4); - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - square_f256(t4, P1->z); - mul_f256(t2, P2->x, t4); - mul_f256(t5, P1->z, t4); - mul_f256(t4, P2->y, t5); - - /* - * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). - * We need to test whether r is zero, so we will do some extra - * reduce. - */ - for (i = 0; i < 20; i ++) { - t2[i] += (F256[i] << 1) - t1[i]; - t4[i] += (F256[i] << 1) - t3[i]; - } - norm13(t2, t2, 20); - norm13(t4, t4, 20); - reduce_f256(t4); - reduce_final_f256(t4); - ret = 0; - for (i = 0; i < 20; i ++) { - ret |= t4[i]; - } - ret = (ret | -ret) >> 31; - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5); - */ - square_f256(t7, t2); - mul_f256(t6, t1, t7); - mul_f256(t5, t7, t2); - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - */ - square_f256(P1->x, t4); - for (i = 0; i < 20; i ++) { - P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1); - } - norm13(P1->x, P1->x, 20); - reduce_f256(P1->x); - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - for (i = 0; i < 20; i ++) { - t6[i] += (F256[i] << 1) - P1->x[i]; - } - norm13(t6, t6, 20); - mul_f256(P1->y, t4, t6); - mul_f256(t1, t5, t3); - for (i = 0; i < 20; i ++) { - P1->y[i] += (F256[i] << 1) - t1[i]; - } - norm13(P1->y, P1->y, 20); - reduce_f256(P1->y); - - /* - * Compute z3 = h*z1*z2. - */ - mul_f256(t1, P1->z, P2->z); - mul_f256(P1->z, t1, t2); - - return ret; -} - -/* - * Add point P2 to point P1. This is a specialised function for the - * case when P2 is a non-zero point in affine coordinate. - * - * This function computes the wrong result in the following cases: - * - * - If P1 == 0 - * - If P1 == P2 - * - * In both cases, P1 is set to the point at infinity. - * - * Returned value is 0 if one of the following occurs: - * - * - P1 and P2 have the same Y coordinate - * - The Y coordinate of P2 is 0 and P1 is the point at infinity. - * - * The second case cannot actually happen with valid points, since a point - * with Y == 0 is a point of order 2, and there is no point of order 2 on - * curve P-256. - * - * Therefore, assuming that P1 != 0 on input, then the caller - * can apply the following: - * - * - If the result is not the point at infinity, then it is correct. - * - Otherwise, if the returned value is 1, then this is a case of - * P1+P2 == 0, so the result is indeed the point at infinity. - * - Otherwise, P1 == P2, so a "double" operation should have been - * performed. - */ -static uint32_t -p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) -{ - /* - * Addtions formulas are: - * - * u1 = x1 - * u2 = x2 * z1^2 - * s1 = y1 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 - */ - uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20]; - uint32_t ret; - int i; - - /* - * Compute u1 = x1 (in t1) and s1 = y1 (in t3). - */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - square_f256(t4, P1->z); - mul_f256(t2, P2->x, t4); - mul_f256(t5, P1->z, t4); - mul_f256(t4, P2->y, t5); - - /* - * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). - * We need to test whether r is zero, so we will do some extra - * reduce. - */ - for (i = 0; i < 20; i ++) { - t2[i] += (F256[i] << 1) - t1[i]; - t4[i] += (F256[i] << 1) - t3[i]; - } - norm13(t2, t2, 20); - norm13(t4, t4, 20); - reduce_f256(t4); - reduce_final_f256(t4); - ret = 0; - for (i = 0; i < 20; i ++) { - ret |= t4[i]; - } - ret = (ret | -ret) >> 31; - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5); - */ - square_f256(t7, t2); - mul_f256(t6, t1, t7); - mul_f256(t5, t7, t2); - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - */ - square_f256(P1->x, t4); - for (i = 0; i < 20; i ++) { - P1->x[i] += (F256[i] << 3) - t5[i] - (t6[i] << 1); - } - norm13(P1->x, P1->x, 20); - reduce_f256(P1->x); - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - for (i = 0; i < 20; i ++) { - t6[i] += (F256[i] << 1) - P1->x[i]; - } - norm13(t6, t6, 20); - mul_f256(P1->y, t4, t6); - mul_f256(t1, t5, t3); - for (i = 0; i < 20; i ++) { - P1->y[i] += (F256[i] << 1) - t1[i]; - } - norm13(P1->y, P1->y, 20); - reduce_f256(P1->y); - - /* - * Compute z3 = h*z1*z2. - */ - mul_f256(P1->z, P1->z, t2); - - return ret; -} - -/* - * Decode a P-256 point. This function does not support the point at - * infinity. Returned value is 0 if the point is invalid, 1 otherwise. - */ -static uint32_t -p256_decode(p256_jacobian *P, const void *src, size_t len) -{ - const unsigned char *buf; - uint32_t tx[20], ty[20], t1[20], t2[20]; - uint32_t bad; - int i; - - if (len != 65) { - return 0; - } - buf = src; - - /* - * First byte must be 0x04 (uncompressed format). We could support - * "hybrid format" (first byte is 0x06 or 0x07, and encodes the - * least significant bit of the Y coordinate), but it is explicitly - * forbidden by RFC 5480 (section 2.2). - */ - bad = NEQ(buf[0], 0x04); - - /* - * Decode the coordinates, and check that they are both lower - * than the modulus. - */ - tx[19] = be8_to_le13(tx, buf + 1, 32); - ty[19] = be8_to_le13(ty, buf + 33, 32); - bad |= reduce_final_f256(tx); - bad |= reduce_final_f256(ty); - - /* - * Check curve equation. - */ - square_f256(t1, tx); - mul_f256(t1, tx, t1); - square_f256(t2, ty); - for (i = 0; i < 20; i ++) { - t1[i] += (F256[i] << 3) - MUL15(3, tx[i]) + P256_B[i] - t2[i]; - } - norm13(t1, t1, 20); - reduce_f256(t1); - reduce_final_f256(t1); - for (i = 0; i < 20; i ++) { - bad |= t1[i]; - } - - /* - * Copy coordinates to the point structure. - */ - memcpy(P->x, tx, sizeof tx); - memcpy(P->y, ty, sizeof ty); - memset(P->z, 0, sizeof P->z); - P->z[0] = 1; - return NEQ(bad, 0) ^ 1; -} - -/* - * Encode a point into a buffer. This function assumes that the point is - * valid, in affine coordinates, and not the point at infinity. - */ -static void -p256_encode(void *dst, const p256_jacobian *P) -{ - unsigned char *buf; - - buf = dst; - buf[0] = 0x04; - le13_to_be8(buf + 1, 32, P->x); - le13_to_be8(buf + 33, 32, P->y); -} - -/* - * Multiply a curve point by an integer. The integer is assumed to be - * lower than the curve order, and the base point must not be the point - * at infinity. - */ -static void -p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) -{ - /* - * qz is a flag that is initially 1, and remains equal to 1 - * as long as the point is the point at infinity. - * - * We use a 2-bit window to handle multiplier bits by pairs. - * The precomputed window really is the points P2 and P3. - */ - uint32_t qz; - p256_jacobian P2, P3, Q, T, U; - - /* - * Compute window values. - */ - P2 = *P; - p256_double(&P2); - P3 = *P; - p256_add(&P3, &P2); - - /* - * We start with Q = 0. We process multiplier bits 2 by 2. - */ - memset(&Q, 0, sizeof Q); - qz = 1; - while (xlen -- > 0) { - int k; - - for (k = 6; k >= 0; k -= 2) { - uint32_t bits; - uint32_t bnz; - - p256_double(&Q); - p256_double(&Q); - T = *P; - U = Q; - bits = (*x >> k) & (uint32_t)3; - bnz = NEQ(bits, 0); - CCOPY(EQ(bits, 2), &T, &P2, sizeof T); - CCOPY(EQ(bits, 3), &T, &P3, sizeof T); - p256_add(&U, &T); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - } - x ++; - } - *P = Q; -} - -/* - * Precomputed window: k*G points, where G is the curve generator, and k - * is an integer from 1 to 15 (inclusive). The X and Y coordinates of - * the point are encoded as 20 words of 13 bits each (little-endian - * order); 13-bit words are then grouped 2-by-2 into 32-bit words - * (little-endian order within each word). - */ -static const uint32_t Gwin[15][20] = { - - { 0x04C60296, 0x02721176, 0x19D00F4A, 0x102517AC, - 0x13B8037D, 0x0748103C, 0x1E730E56, 0x08481FE2, - 0x0F97012C, 0x00D605F4, 0x1DFA11F5, 0x0C801A0D, - 0x0F670CBB, 0x0AED0CC5, 0x115E0E33, 0x181F0785, - 0x13F514A7, 0x0FF30E3B, 0x17171E1A, 0x009F18D0 }, - - { 0x1B341978, 0x16911F11, 0x0D9A1A60, 0x1C4E1FC8, - 0x1E040969, 0x096A06B0, 0x091C0030, 0x09EF1A29, - 0x18C40D03, 0x00F91C9E, 0x13C313D1, 0x096F0748, - 0x011419E0, 0x1CC713A6, 0x1DD31DAD, 0x1EE80C36, - 0x1ECD0C69, 0x1A0800A4, 0x08861B8E, 0x000E1DD5 }, - - { 0x173F1D6C, 0x02CC06F1, 0x14C21FB4, 0x043D1EB6, - 0x0F3606B7, 0x1A971C59, 0x1BF71951, 0x01481323, - 0x068D0633, 0x00BD12F9, 0x13EA1032, 0x136209E8, - 0x1C1E19A7, 0x06C7013E, 0x06C10AB0, 0x14C908BB, - 0x05830CE1, 0x1FEF18DD, 0x00620998, 0x010E0D19 }, - - { 0x18180852, 0x0604111A, 0x0B771509, 0x1B6F0156, - 0x00181FE2, 0x1DCC0AF4, 0x16EF0659, 0x11F70E80, - 0x11A912D0, 0x01C414D2, 0x027618C6, 0x05840FC6, - 0x100215C4, 0x187E0C3B, 0x12771C96, 0x150C0B5D, - 0x0FF705FD, 0x07981C67, 0x1AD20C63, 0x01C11C55 }, - - { 0x1E8113ED, 0x0A940370, 0x12920215, 0x1FA31D6F, - 0x1F7C0C82, 0x10CD03F7, 0x02640560, 0x081A0B5E, - 0x1BD21151, 0x00A21642, 0x0D0B0DA4, 0x0176113F, - 0x04440D1D, 0x001A1360, 0x1068012F, 0x1F141E49, - 0x10DF136B, 0x0E4F162B, 0x0D44104A, 0x01C1105F }, - - { 0x011411A9, 0x01551A4F, 0x0ADA0C6B, 0x01BD0EC8, - 0x18120C74, 0x112F1778, 0x099202CB, 0x0C05124B, - 0x195316A4, 0x01600685, 0x1E3B1FE2, 0x189014E3, - 0x0B5E1FD7, 0x0E0311F8, 0x08E000F7, 0x174E00DE, - 0x160702DF, 0x1B5A15BF, 0x03A11237, 0x01D01704 }, - - { 0x0C3D12A3, 0x0C501C0C, 0x17AD1300, 0x1715003F, - 0x03F719F8, 0x18031ED8, 0x1D980667, 0x0F681896, - 0x1B7D00BF, 0x011C14CE, 0x0FA000B4, 0x1C3501B0, - 0x0D901C55, 0x06790C10, 0x029E0736, 0x0DEB0400, - 0x034F183A, 0x030619B4, 0x0DEF0033, 0x00E71AC7 }, - - { 0x1B7D1393, 0x1B3B1076, 0x0BED1B4D, 0x13011F3A, - 0x0E0E1238, 0x156A132B, 0x013A02D3, 0x160A0D01, - 0x1CED1EE9, 0x00C5165D, 0x184C157E, 0x08141A83, - 0x153C0DA5, 0x1ED70F9D, 0x05170D51, 0x02CF13B8, - 0x18AE1771, 0x1B04113F, 0x05EC11E9, 0x015A16B3 }, - - { 0x04A41EE0, 0x1D1412E4, 0x1C591D79, 0x118511B7, - 0x14F00ACB, 0x1AE31E1C, 0x049C0D51, 0x016E061E, - 0x1DB71EDF, 0x01D41A35, 0x0E8208FA, 0x14441293, - 0x011F1E85, 0x1D54137A, 0x026B114F, 0x151D0832, - 0x00A50964, 0x1F9C1E1C, 0x064B12C9, 0x005409D1 }, - - { 0x062B123F, 0x0C0D0501, 0x183704C3, 0x08E31120, - 0x0A2E0A6C, 0x14440FED, 0x090A0D1E, 0x13271964, - 0x0B590A3A, 0x019D1D9B, 0x05780773, 0x09770A91, - 0x0F770CA3, 0x053F19D4, 0x02C80DED, 0x1A761304, - 0x091E0DD9, 0x15D201B8, 0x151109AA, 0x010F0198 }, - - { 0x05E101D1, 0x072314DD, 0x045F1433, 0x1A041541, - 0x10B3142E, 0x01840736, 0x1C1B19DB, 0x098B0418, - 0x1DBC083B, 0x007D1444, 0x01511740, 0x11DD1F3A, - 0x04ED0E2F, 0x1B4B1A62, 0x10480D04, 0x09E911A2, - 0x04211AFA, 0x19140893, 0x04D60CC4, 0x01210648 }, - - { 0x112703C4, 0x018B1BA1, 0x164C1D50, 0x05160BE0, - 0x0BCC1830, 0x01CB1554, 0x13291732, 0x1B2B1918, - 0x0DED0817, 0x00E80775, 0x0A2401D3, 0x0BFE08B3, - 0x0E531199, 0x058616E9, 0x04770B91, 0x110F0C55, - 0x19C11554, 0x0BFB1159, 0x03541C38, 0x000E1C2D }, - - { 0x10390C01, 0x02BB0751, 0x0AC5098E, 0x096C17AB, - 0x03C90E28, 0x10BD18BF, 0x002E1F2D, 0x092B0986, - 0x1BD700AC, 0x002E1F20, 0x1E3D1FD8, 0x077718BB, - 0x06F919C4, 0x187407ED, 0x11370E14, 0x081E139C, - 0x00481ADB, 0x14AB0289, 0x066A0EBE, 0x00C70ED6 }, - - { 0x0694120B, 0x124E1CC9, 0x0E2F0570, 0x17CF081A, - 0x078906AC, 0x066D17CF, 0x1B3207F4, 0x0C5705E9, - 0x10001C38, 0x00A919DE, 0x06851375, 0x0F900BD8, - 0x080401BA, 0x0EEE0D42, 0x1B8B11EA, 0x0B4519F0, - 0x090F18C0, 0x062E1508, 0x0DD909F4, 0x01EB067C }, - - { 0x0CDC1D5F, 0x0D1818F9, 0x07781636, 0x125B18E8, - 0x0D7003AF, 0x13110099, 0x1D9B1899, 0x175C1EB7, - 0x0E34171A, 0x01E01153, 0x081A0F36, 0x0B391783, - 0x1D1F147E, 0x19CE16D7, 0x11511B21, 0x1F2C10F9, - 0x12CA0E51, 0x05A31D39, 0x171A192E, 0x016B0E4F } -}; - -/* - * Lookup one of the Gwin[] values, by index. This is constant-time. - */ -static void -lookup_Gwin(p256_jacobian *T, uint32_t idx) -{ - uint32_t xy[20]; - uint32_t k; - size_t u; - - memset(xy, 0, sizeof xy); - for (k = 0; k < 15; k ++) { - uint32_t m; - - m = -EQ(idx, k + 1); - for (u = 0; u < 20; u ++) { - xy[u] |= m & Gwin[k][u]; - } - } - for (u = 0; u < 10; u ++) { - T->x[(u << 1) + 0] = xy[u] & 0xFFFF; - T->x[(u << 1) + 1] = xy[u] >> 16; - T->y[(u << 1) + 0] = xy[u + 10] & 0xFFFF; - T->y[(u << 1) + 1] = xy[u + 10] >> 16; - } - memset(T->z, 0, sizeof T->z); - T->z[0] = 1; -} - -/* - * Multiply the generator by an integer. The integer is assumed non-zero - * and lower than the curve order. - */ -static void -p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) -{ - /* - * qz is a flag that is initially 1, and remains equal to 1 - * as long as the point is the point at infinity. - * - * We use a 4-bit window to handle multiplier bits by groups - * of 4. The precomputed window is constant static data, with - * points in affine coordinates; we use a constant-time lookup. - */ - p256_jacobian Q; - uint32_t qz; - - memset(&Q, 0, sizeof Q); - qz = 1; - while (xlen -- > 0) { - int k; - unsigned bx; - - bx = *x ++; - for (k = 0; k < 2; k ++) { - uint32_t bits; - uint32_t bnz; - p256_jacobian T, U; - - p256_double(&Q); - p256_double(&Q); - p256_double(&Q); - p256_double(&Q); - bits = (bx >> 4) & 0x0F; - bnz = NEQ(bits, 0); - lookup_Gwin(&T, bits); - U = Q; - p256_add_mixed(&U, &T); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - bx <<= 4; - } - } - *P = Q; -} - -static const unsigned char P256_G[] = { - 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, - 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, - 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, - 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, - 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, - 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, - 0x68, 0x37, 0xBF, 0x51, 0xF5 -}; - -static const unsigned char P256_N[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, - 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, - 0x25, 0x51 -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = sizeof P256_G; - return P256_G; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = sizeof P256_N; - return P256_N; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 1; -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *x, size_t xlen, int curve) -{ - uint32_t r; - p256_jacobian P; - - (void)curve; - r = p256_decode(&P, G, Glen); - p256_mul(&P, x, xlen); - if (Glen >= 65) { - p256_to_affine(&P); - p256_encode(G, &P); - } - return r; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - p256_jacobian P; - - (void)curve; - p256_mulgen(&P, x, xlen); - p256_to_affine(&P); - p256_encode(R, &P); - return 65; - - /* - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; - */ -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - p256_jacobian P, Q; - uint32_t r, t, z; - int i; - - (void)curve; - r = p256_decode(&P, A, len); - p256_mul(&P, x, xlen); - if (B == NULL) { - p256_mulgen(&Q, y, ylen); - } else { - r &= p256_decode(&Q, B, len); - p256_mul(&Q, y, ylen); - } - - /* - * The final addition may fail in case both points are equal. - */ - t = p256_add(&P, &Q); - reduce_final_f256(P.z); - z = 0; - for (i = 0; i < 20; i ++) { - z |= P.z[i]; - } - z = EQ(z, 0); - p256_double(&Q); - - /* - * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we - * have the following: - * - * z = 0, t = 0 return P (normal addition) - * z = 0, t = 1 return P (normal addition) - * z = 1, t = 0 return Q (a 'double' case) - * z = 1, t = 1 report an error (P+Q = 0) - */ - CCOPY(z & ~t, &P, &Q, sizeof Q); - p256_to_affine(&P); - p256_encode(A, &P); - r &= ~(z & t); - return r; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_p256_m15 = { - (uint32_t)0x00800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_p256_m31.c b/src/tls/bearssl/ec_p256_m31.c deleted file mode 100644 index 9e7e83fea..000000000 --- a/src/tls/bearssl/ec_p256_m31.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_ - * that right-shifting a signed negative integer copies the sign bit - * (arithmetic right-shift). This is "implementation-defined behaviour", - * i.e. it is not undefined, but it may differ between compilers. Each - * compiler is supposed to document its behaviour in that respect. GCC - * explicitly defines that an arithmetic right shift is used. We expect - * all other compilers to do the same, because underlying CPU offer an - * arithmetic right shift opcode that could not be used otherwise. - */ -#if BR_NO_ARITH_SHIFT -#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ - | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) -#define ARSHW(x, n) (((uint64_t)(x) >> (n)) \ - | ((-((uint64_t)(x) >> 63)) << (64 - (n)))) -#else -#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) -#define ARSHW(x, n) ((*(int64_t *)&(x)) >> (n)) -#endif - -/* - * Convert an integer from unsigned big-endian encoding to a sequence of - * 30-bit words in little-endian order. The final "partial" word is - * returned. - */ -static uint32_t -be8_to_le30(uint32_t *dst, const unsigned char *src, size_t len) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - uint32_t b; - - b = src[len]; - if (acc_len < 22) { - acc |= b << acc_len; - acc_len += 8; - } else { - *dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF; - acc = b >> (30 - acc_len); - acc_len -= 22; - } - } - return acc; -} - -/* - * Convert an integer (30-bit words, little-endian) to unsigned - * big-endian encoding. The total encoding length is provided; all - * the destination bytes will be filled. - */ -static void -le30_to_be8(unsigned char *dst, size_t len, const uint32_t *src) -{ - uint32_t acc; - int acc_len; - - acc = 0; - acc_len = 0; - while (len -- > 0) { - if (acc_len < 8) { - uint32_t w; - - w = *src ++; - dst[len] = (unsigned char)(acc | (w << acc_len)); - acc = w >> (8 - acc_len); - acc_len += 22; - } else { - dst[len] = (unsigned char)acc; - acc >>= 8; - acc_len -= 8; - } - } -} - -/* - * Multiply two integers. Source integers are represented as arrays of - * nine 30-bit words, for values up to 2^270-1. Result is encoded over - * 18 words of 30 bits each. - */ -static void -mul9(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - /* - * Maximum intermediate result is no more than - * 10376293531797946367, which fits in 64 bits. Reason: - * - * 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406 - * 10376293531797946367 < 9663676407 * 2^30 - * - * Thus, adding together 9 products of 30-bit integers, with - * a carry of at most 9663676406, yields an integer that fits - * on 64 bits and generates a carry of at most 9663676406. - */ - uint64_t t[17]; - uint64_t cc; - int i; - - t[ 0] = MUL31(a[0], b[0]); - t[ 1] = MUL31(a[0], b[1]) - + MUL31(a[1], b[0]); - t[ 2] = MUL31(a[0], b[2]) - + MUL31(a[1], b[1]) - + MUL31(a[2], b[0]); - t[ 3] = MUL31(a[0], b[3]) - + MUL31(a[1], b[2]) - + MUL31(a[2], b[1]) - + MUL31(a[3], b[0]); - t[ 4] = MUL31(a[0], b[4]) - + MUL31(a[1], b[3]) - + MUL31(a[2], b[2]) - + MUL31(a[3], b[1]) - + MUL31(a[4], b[0]); - t[ 5] = MUL31(a[0], b[5]) - + MUL31(a[1], b[4]) - + MUL31(a[2], b[3]) - + MUL31(a[3], b[2]) - + MUL31(a[4], b[1]) - + MUL31(a[5], b[0]); - t[ 6] = MUL31(a[0], b[6]) - + MUL31(a[1], b[5]) - + MUL31(a[2], b[4]) - + MUL31(a[3], b[3]) - + MUL31(a[4], b[2]) - + MUL31(a[5], b[1]) - + MUL31(a[6], b[0]); - t[ 7] = MUL31(a[0], b[7]) - + MUL31(a[1], b[6]) - + MUL31(a[2], b[5]) - + MUL31(a[3], b[4]) - + MUL31(a[4], b[3]) - + MUL31(a[5], b[2]) - + MUL31(a[6], b[1]) - + MUL31(a[7], b[0]); - t[ 8] = MUL31(a[0], b[8]) - + MUL31(a[1], b[7]) - + MUL31(a[2], b[6]) - + MUL31(a[3], b[5]) - + MUL31(a[4], b[4]) - + MUL31(a[5], b[3]) - + MUL31(a[6], b[2]) - + MUL31(a[7], b[1]) - + MUL31(a[8], b[0]); - t[ 9] = MUL31(a[1], b[8]) - + MUL31(a[2], b[7]) - + MUL31(a[3], b[6]) - + MUL31(a[4], b[5]) - + MUL31(a[5], b[4]) - + MUL31(a[6], b[3]) - + MUL31(a[7], b[2]) - + MUL31(a[8], b[1]); - t[10] = MUL31(a[2], b[8]) - + MUL31(a[3], b[7]) - + MUL31(a[4], b[6]) - + MUL31(a[5], b[5]) - + MUL31(a[6], b[4]) - + MUL31(a[7], b[3]) - + MUL31(a[8], b[2]); - t[11] = MUL31(a[3], b[8]) - + MUL31(a[4], b[7]) - + MUL31(a[5], b[6]) - + MUL31(a[6], b[5]) - + MUL31(a[7], b[4]) - + MUL31(a[8], b[3]); - t[12] = MUL31(a[4], b[8]) - + MUL31(a[5], b[7]) - + MUL31(a[6], b[6]) - + MUL31(a[7], b[5]) - + MUL31(a[8], b[4]); - t[13] = MUL31(a[5], b[8]) - + MUL31(a[6], b[7]) - + MUL31(a[7], b[6]) - + MUL31(a[8], b[5]); - t[14] = MUL31(a[6], b[8]) - + MUL31(a[7], b[7]) - + MUL31(a[8], b[6]); - t[15] = MUL31(a[7], b[8]) - + MUL31(a[8], b[7]); - t[16] = MUL31(a[8], b[8]); - - /* - * Propagate carries. - */ - cc = 0; - for (i = 0; i < 17; i ++) { - uint64_t w; - - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - d[17] = (uint32_t)cc; -} - -/* - * Square a 270-bit integer, represented as an array of nine 30-bit words. - * Result uses 18 words of 30 bits each. - */ -static void -square9(uint32_t *d, const uint32_t *a) -{ - uint64_t t[17]; - uint64_t cc; - int i; - - t[ 0] = MUL31(a[0], a[0]); - t[ 1] = ((MUL31(a[0], a[1])) << 1); - t[ 2] = MUL31(a[1], a[1]) - + ((MUL31(a[0], a[2])) << 1); - t[ 3] = ((MUL31(a[0], a[3]) - + MUL31(a[1], a[2])) << 1); - t[ 4] = MUL31(a[2], a[2]) - + ((MUL31(a[0], a[4]) - + MUL31(a[1], a[3])) << 1); - t[ 5] = ((MUL31(a[0], a[5]) - + MUL31(a[1], a[4]) - + MUL31(a[2], a[3])) << 1); - t[ 6] = MUL31(a[3], a[3]) - + ((MUL31(a[0], a[6]) - + MUL31(a[1], a[5]) - + MUL31(a[2], a[4])) << 1); - t[ 7] = ((MUL31(a[0], a[7]) - + MUL31(a[1], a[6]) - + MUL31(a[2], a[5]) - + MUL31(a[3], a[4])) << 1); - t[ 8] = MUL31(a[4], a[4]) - + ((MUL31(a[0], a[8]) - + MUL31(a[1], a[7]) - + MUL31(a[2], a[6]) - + MUL31(a[3], a[5])) << 1); - t[ 9] = ((MUL31(a[1], a[8]) - + MUL31(a[2], a[7]) - + MUL31(a[3], a[6]) - + MUL31(a[4], a[5])) << 1); - t[10] = MUL31(a[5], a[5]) - + ((MUL31(a[2], a[8]) - + MUL31(a[3], a[7]) - + MUL31(a[4], a[6])) << 1); - t[11] = ((MUL31(a[3], a[8]) - + MUL31(a[4], a[7]) - + MUL31(a[5], a[6])) << 1); - t[12] = MUL31(a[6], a[6]) - + ((MUL31(a[4], a[8]) - + MUL31(a[5], a[7])) << 1); - t[13] = ((MUL31(a[5], a[8]) - + MUL31(a[6], a[7])) << 1); - t[14] = MUL31(a[7], a[7]) - + ((MUL31(a[6], a[8])) << 1); - t[15] = ((MUL31(a[7], a[8])) << 1); - t[16] = MUL31(a[8], a[8]); - - /* - * Propagate carries. - */ - cc = 0; - for (i = 0; i < 17; i ++) { - uint64_t w; - - w = t[i] + cc; - d[i] = (uint32_t)w & 0x3FFFFFFF; - cc = w >> 30; - } - d[17] = (uint32_t)cc; -} - -/* - * Base field modulus for P-256. - */ -static const uint32_t F256[] = { - - 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x0000003F, 0x00000000, - 0x00000000, 0x00001000, 0x3FFFC000, 0x0000FFFF -}; - -/* - * The 'b' curve equation coefficient for P-256. - */ -static const uint32_t P256_B[] = { - - 0x27D2604B, 0x2F38F0F8, 0x053B0F63, 0x0741AC33, 0x1886BC65, - 0x2EF555DA, 0x293E7B3E, 0x0D762A8E, 0x00005AC6 -}; - -/* - * Addition in the field. Source operands shall fit on 257 bits; output - * will be lower than twice the modulus. - */ -static void -add_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t w, cc; - int i; - - cc = 0; - for (i = 0; i < 9; i ++) { - w = a[i] + b[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = w >> 30; - } - w >>= 16; - d[8] &= 0xFFFF; - d[3] -= w << 6; - d[6] -= w << 12; - d[7] += w << 14; - cc = w; - for (i = 0; i < 9; i ++) { - w = d[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = ARSH(w, 30); - } -} - -/* - * Subtraction in the field. Source operands shall be smaller than twice - * the modulus; the result will fulfill the same property. - */ -static void -sub_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t w, cc; - int i; - - /* - * We really compute a - b + 2*p to make sure that the result is - * positive. - */ - w = a[0] - b[0] - 0x00002; - d[0] = w & 0x3FFFFFFF; - w = a[1] - b[1] + ARSH(w, 30); - d[1] = w & 0x3FFFFFFF; - w = a[2] - b[2] + ARSH(w, 30); - d[2] = w & 0x3FFFFFFF; - w = a[3] - b[3] + ARSH(w, 30) + 0x00080; - d[3] = w & 0x3FFFFFFF; - w = a[4] - b[4] + ARSH(w, 30); - d[4] = w & 0x3FFFFFFF; - w = a[5] - b[5] + ARSH(w, 30); - d[5] = w & 0x3FFFFFFF; - w = a[6] - b[6] + ARSH(w, 30) + 0x02000; - d[6] = w & 0x3FFFFFFF; - w = a[7] - b[7] + ARSH(w, 30) - 0x08000; - d[7] = w & 0x3FFFFFFF; - w = a[8] - b[8] + ARSH(w, 30) + 0x20000; - d[8] = w & 0xFFFF; - w >>= 16; - d[8] &= 0xFFFF; - d[3] -= w << 6; - d[6] -= w << 12; - d[7] += w << 14; - cc = w; - for (i = 0; i < 9; i ++) { - w = d[i] + cc; - d[i] = w & 0x3FFFFFFF; - cc = ARSH(w, 30); - } -} - -/* - * Compute a multiplication in F256. Source operands shall be less than - * twice the modulus. - */ -static void -mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - uint32_t t[18]; - uint64_t s[18]; - uint64_t cc, x; - uint32_t z, c; - int i; - - mul9(t, a, b); - - /* - * Modular reduction: each high word in added/subtracted where - * necessary. - * - * The modulus is: - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 - * Therefore: - * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p - * - * For a word x at bit offset n (n >= 256), we have: - * x*2^n = x*2^(n-32) - x*2^(n-64) - * - x*2^(n - 160) + x*2^(n-256) mod p - * - * Thus, we can nullify the high word if we reinject it at some - * proper emplacements. - * - * We use 64-bit intermediate words to allow for carries to - * accumulate easily, before performing the final propagation. - */ - for (i = 0; i < 18; i ++) { - s[i] = t[i]; - } - - for (i = 17; i >= 9; i --) { - uint64_t y; - - y = s[i]; - s[i - 1] += ARSHW(y, 2); - s[i - 2] += (y << 28) & 0x3FFFFFFF; - s[i - 2] -= ARSHW(y, 4); - s[i - 3] -= (y << 26) & 0x3FFFFFFF; - s[i - 5] -= ARSHW(y, 10); - s[i - 6] -= (y << 20) & 0x3FFFFFFF; - s[i - 8] += ARSHW(y, 16); - s[i - 9] += (y << 14) & 0x3FFFFFFF; - } - - /* - * Carry propagation must be signed. Moreover, we may have overdone - * it a bit, and obtain a negative result. - * - * The loop above ran 9 times; each time, each word was augmented - * by at most one extra word (in absolute value). Thus, the top - * word must in fine fit in 39 bits, so the carry below will fit - * on 9 bits. - */ - cc = 0; - for (i = 0; i < 9; i ++) { - x = s[i] + cc; - d[i] = (uint32_t)x & 0x3FFFFFFF; - cc = ARSHW(x, 30); - } - - /* - * All nine words fit on 30 bits, but there may be an extra - * carry for a few bits (at most 9), and that carry may be - * negative. Moreover, we want the result to fit on 257 bits. - * The two lines below ensure that the word in d[] has length - * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The - * significant length of cc is less than 24 bits, so we will be - * able to switch to 32-bit operations. - */ - cc = ARSHW(x, 16); - d[8] &= 0xFFFF; - - /* - * One extra round of reduction, for cc*2^256, which means - * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative) - * value. If cc is negative, then it may happen (rarely, but - * not neglectibly so) that the result would be negative. In - * order to avoid that, if cc is negative, then we add the - * modulus once. Note that if cc is negative, then propagating - * that carry must yield a value lower than the modulus, so - * adding the modulus once will keep the final result under - * twice the modulus. - */ - z = (uint32_t)cc; - d[3] -= z << 6; - d[6] -= (z << 12) & 0x3FFFFFFF; - d[7] -= ARSH(z, 18); - d[7] += (z << 14) & 0x3FFFFFFF; - d[8] += ARSH(z, 16); - c = z >> 31; - d[0] -= c; - d[3] += c << 6; - d[6] += c << 12; - d[7] -= c << 14; - d[8] += c << 16; - for (i = 0; i < 9; i ++) { - uint32_t w; - - w = d[i] + z; - d[i] = w & 0x3FFFFFFF; - z = ARSH(w, 30); - } -} - -/* - * Compute a square in F256. Source operand shall be less than - * twice the modulus. - */ -static void -square_f256(uint32_t *d, const uint32_t *a) -{ - uint32_t t[18]; - uint64_t s[18]; - uint64_t cc, x; - uint32_t z, c; - int i; - - square9(t, a); - - /* - * Modular reduction: each high word in added/subtracted where - * necessary. - * - * The modulus is: - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1 - * Therefore: - * 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p - * - * For a word x at bit offset n (n >= 256), we have: - * x*2^n = x*2^(n-32) - x*2^(n-64) - * - x*2^(n - 160) + x*2^(n-256) mod p - * - * Thus, we can nullify the high word if we reinject it at some - * proper emplacements. - * - * We use 64-bit intermediate words to allow for carries to - * accumulate easily, before performing the final propagation. - */ - for (i = 0; i < 18; i ++) { - s[i] = t[i]; - } - - for (i = 17; i >= 9; i --) { - uint64_t y; - - y = s[i]; - s[i - 1] += ARSHW(y, 2); - s[i - 2] += (y << 28) & 0x3FFFFFFF; - s[i - 2] -= ARSHW(y, 4); - s[i - 3] -= (y << 26) & 0x3FFFFFFF; - s[i - 5] -= ARSHW(y, 10); - s[i - 6] -= (y << 20) & 0x3FFFFFFF; - s[i - 8] += ARSHW(y, 16); - s[i - 9] += (y << 14) & 0x3FFFFFFF; - } - - /* - * Carry propagation must be signed. Moreover, we may have overdone - * it a bit, and obtain a negative result. - * - * The loop above ran 9 times; each time, each word was augmented - * by at most one extra word (in absolute value). Thus, the top - * word must in fine fit in 39 bits, so the carry below will fit - * on 9 bits. - */ - cc = 0; - for (i = 0; i < 9; i ++) { - x = s[i] + cc; - d[i] = (uint32_t)x & 0x3FFFFFFF; - cc = ARSHW(x, 30); - } - - /* - * All nine words fit on 30 bits, but there may be an extra - * carry for a few bits (at most 9), and that carry may be - * negative. Moreover, we want the result to fit on 257 bits. - * The two lines below ensure that the word in d[] has length - * 256 bits, and the (signed) carry (beyond 2^256) is in cc. The - * significant length of cc is less than 24 bits, so we will be - * able to switch to 32-bit operations. - */ - cc = ARSHW(x, 16); - d[8] &= 0xFFFF; - - /* - * One extra round of reduction, for cc*2^256, which means - * adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative) - * value. If cc is negative, then it may happen (rarely, but - * not neglectibly so) that the result would be negative. In - * order to avoid that, if cc is negative, then we add the - * modulus once. Note that if cc is negative, then propagating - * that carry must yield a value lower than the modulus, so - * adding the modulus once will keep the final result under - * twice the modulus. - */ - z = (uint32_t)cc; - d[3] -= z << 6; - d[6] -= (z << 12) & 0x3FFFFFFF; - d[7] -= ARSH(z, 18); - d[7] += (z << 14) & 0x3FFFFFFF; - d[8] += ARSH(z, 16); - c = z >> 31; - d[0] -= c; - d[3] += c << 6; - d[6] += c << 12; - d[7] -= c << 14; - d[8] += c << 16; - for (i = 0; i < 9; i ++) { - uint32_t w; - - w = d[i] + z; - d[i] = w & 0x3FFFFFFF; - z = ARSH(w, 30); - } -} - -/* - * Perform a "final reduction" in field F256 (field for curve P-256). - * The source value must be less than twice the modulus. If the value - * is not lower than the modulus, then the modulus is subtracted and - * this function returns 1; otherwise, it leaves it untouched and it - * returns 0. - */ -static uint32_t -reduce_final_f256(uint32_t *d) -{ - uint32_t t[9]; - uint32_t cc; - int i; - - cc = 0; - for (i = 0; i < 9; i ++) { - uint32_t w; - - w = d[i] - F256[i] - cc; - cc = w >> 31; - t[i] = w & 0x3FFFFFFF; - } - cc ^= 1; - CCOPY(cc, d, t, sizeof t); - return cc; -} - -/* - * Jacobian coordinates for a point in P-256: affine coordinates (X,Y) - * are such that: - * X = x / z^2 - * Y = y / z^3 - * For the point at infinity, z = 0. - * Each point thus admits many possible representations. - * - * Coordinates are represented in arrays of 32-bit integers, each holding - * 30 bits of data. Values may also be slightly greater than the modulus, - * but they will always be lower than twice the modulus. - */ -typedef struct { - uint32_t x[9]; - uint32_t y[9]; - uint32_t z[9]; -} p256_jacobian; - -/* - * Convert a point to affine coordinates: - * - If the point is the point at infinity, then all three coordinates - * are set to 0. - * - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y' - * coordinates are the 'X' and 'Y' affine coordinates. - * The coordinates are guaranteed to be lower than the modulus. - */ -static void -p256_to_affine(p256_jacobian *P) -{ - uint32_t t1[9], t2[9]; - int i; - - /* - * Invert z with a modular exponentiation: the modulus is - * p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is - * p-2. Exponent bit pattern (from high to low) is: - * - 32 bits of value 1 - * - 31 bits of value 0 - * - 1 bit of value 1 - * - 96 bits of value 0 - * - 94 bits of value 1 - * - 1 bit of value 0 - * - 1 bit of value 1 - * Thus, we precompute z^(2^31-1) to speed things up. - * - * If z = 0 (point at infinity) then the modular exponentiation - * will yield 0, which leads to the expected result (all three - * coordinates set to 0). - */ - - /* - * A simple square-and-multiply for z^(2^31-1). We could save about - * two dozen multiplications here with an addition chain, but - * this would require a bit more code, and extra stack buffers. - */ - memcpy(t1, P->z, sizeof P->z); - for (i = 0; i < 30; i ++) { - square_f256(t1, t1); - mul_f256(t1, t1, P->z); - } - - /* - * Square-and-multiply. Apart from the squarings, we have a few - * multiplications to set bits to 1; we multiply by the original z - * for setting 1 bit, and by t1 for setting 31 bits. - */ - memcpy(t2, P->z, sizeof P->z); - for (i = 1; i < 256; i ++) { - square_f256(t2, t2); - switch (i) { - case 31: - case 190: - case 221: - case 252: - mul_f256(t2, t2, t1); - break; - case 63: - case 253: - case 255: - mul_f256(t2, t2, P->z); - break; - } - } - - /* - * Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3. - */ - mul_f256(t1, t2, t2); - mul_f256(P->x, t1, P->x); - mul_f256(t1, t1, t2); - mul_f256(P->y, t1, P->y); - reduce_final_f256(P->x); - reduce_final_f256(P->y); - - /* - * Multiply z by 1/z. If z = 0, then this will yield 0, otherwise - * this will set z to 1. - */ - mul_f256(P->z, P->z, t2); - reduce_final_f256(P->z); -} - -/* - * Double a point in P-256. This function works for all valid points, - * including the point at infinity. - */ -static void -p256_double(p256_jacobian *Q) -{ - /* - * Doubling formulas are: - * - * s = 4*x*y^2 - * m = 3*(x + z^2)*(x - z^2) - * x' = m^2 - 2*s - * y' = m*(s - x') - 8*y^4 - * z' = 2*y*z - * - * These formulas work for all points, including points of order 2 - * and points at infinity: - * - If y = 0 then z' = 0. But there is no such point in P-256 - * anyway. - * - If z = 0 then z' = 0. - */ - uint32_t t1[9], t2[9], t3[9], t4[9]; - - /* - * Compute z^2 in t1. - */ - square_f256(t1, Q->z); - - /* - * Compute x-z^2 in t2 and x+z^2 in t1. - */ - add_f256(t2, Q->x, t1); - sub_f256(t1, Q->x, t1); - - /* - * Compute 3*(x+z^2)*(x-z^2) in t1. - */ - mul_f256(t3, t1, t2); - add_f256(t1, t3, t3); - add_f256(t1, t3, t1); - - /* - * Compute 4*x*y^2 (in t2) and 2*y^2 (in t3). - */ - square_f256(t3, Q->y); - add_f256(t3, t3, t3); - mul_f256(t2, Q->x, t3); - add_f256(t2, t2, t2); - - /* - * Compute x' = m^2 - 2*s. - */ - square_f256(Q->x, t1); - sub_f256(Q->x, Q->x, t2); - sub_f256(Q->x, Q->x, t2); - - /* - * Compute z' = 2*y*z. - */ - mul_f256(t4, Q->y, Q->z); - add_f256(Q->z, t4, t4); - - /* - * Compute y' = m*(s - x') - 8*y^4. Note that we already have - * 2*y^2 in t3. - */ - sub_f256(t2, t2, Q->x); - mul_f256(Q->y, t1, t2); - square_f256(t4, t3); - add_f256(t4, t4, t4); - sub_f256(Q->y, Q->y, t4); -} - -/* - * Add point P2 to point P1. - * - * This function computes the wrong result in the following cases: - * - * - If P1 == 0 but P2 != 0 - * - If P1 != 0 but P2 == 0 - * - If P1 == P2 - * - * In all three cases, P1 is set to the point at infinity. - * - * Returned value is 0 if one of the following occurs: - * - * - P1 and P2 have the same Y coordinate - * - P1 == 0 and P2 == 0 - * - The Y coordinate of one of the points is 0 and the other point is - * the point at infinity. - * - * The third case cannot actually happen with valid points, since a point - * with Y == 0 is a point of order 2, and there is no point of order 2 on - * curve P-256. - * - * Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller - * can apply the following: - * - * - If the result is not the point at infinity, then it is correct. - * - Otherwise, if the returned value is 1, then this is a case of - * P1+P2 == 0, so the result is indeed the point at infinity. - * - Otherwise, P1 == P2, so a "double" operation should have been - * performed. - */ -static uint32_t -p256_add(p256_jacobian *P1, const p256_jacobian *P2) -{ - /* - * Addtions formulas are: - * - * u1 = x1 * z2^2 - * u2 = x2 * z1^2 - * s1 = y1 * z2^3 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 * z2 - */ - uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9]; - uint32_t ret; - int i; - - /* - * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). - */ - square_f256(t3, P2->z); - mul_f256(t1, P1->x, t3); - mul_f256(t4, P2->z, t3); - mul_f256(t3, P1->y, t4); - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - square_f256(t4, P1->z); - mul_f256(t2, P2->x, t4); - mul_f256(t5, P1->z, t4); - mul_f256(t4, P2->y, t5); - - /* - * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). - * We need to test whether r is zero, so we will do some extra - * reduce. - */ - sub_f256(t2, t2, t1); - sub_f256(t4, t4, t3); - reduce_final_f256(t4); - ret = 0; - for (i = 0; i < 9; i ++) { - ret |= t4[i]; - } - ret = (ret | -ret) >> 31; - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5); - */ - square_f256(t7, t2); - mul_f256(t6, t1, t7); - mul_f256(t5, t7, t2); - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - */ - square_f256(P1->x, t4); - sub_f256(P1->x, P1->x, t5); - sub_f256(P1->x, P1->x, t6); - sub_f256(P1->x, P1->x, t6); - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - sub_f256(t6, t6, P1->x); - mul_f256(P1->y, t4, t6); - mul_f256(t1, t5, t3); - sub_f256(P1->y, P1->y, t1); - - /* - * Compute z3 = h*z1*z2. - */ - mul_f256(t1, P1->z, P2->z); - mul_f256(P1->z, t1, t2); - - return ret; -} - -/* - * Add point P2 to point P1. This is a specialised function for the - * case when P2 is a non-zero point in affine coordinate. - * - * This function computes the wrong result in the following cases: - * - * - If P1 == 0 - * - If P1 == P2 - * - * In both cases, P1 is set to the point at infinity. - * - * Returned value is 0 if one of the following occurs: - * - * - P1 and P2 have the same Y coordinate - * - The Y coordinate of P2 is 0 and P1 is the point at infinity. - * - * The second case cannot actually happen with valid points, since a point - * with Y == 0 is a point of order 2, and there is no point of order 2 on - * curve P-256. - * - * Therefore, assuming that P1 != 0 on input, then the caller - * can apply the following: - * - * - If the result is not the point at infinity, then it is correct. - * - Otherwise, if the returned value is 1, then this is a case of - * P1+P2 == 0, so the result is indeed the point at infinity. - * - Otherwise, P1 == P2, so a "double" operation should have been - * performed. - */ -static uint32_t -p256_add_mixed(p256_jacobian *P1, const p256_jacobian *P2) -{ - /* - * Addtions formulas are: - * - * u1 = x1 - * u2 = x2 * z1^2 - * s1 = y1 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 - */ - uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9]; - uint32_t ret; - int i; - - /* - * Compute u1 = x1 (in t1) and s1 = y1 (in t3). - */ - memcpy(t1, P1->x, sizeof t1); - memcpy(t3, P1->y, sizeof t3); - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - square_f256(t4, P1->z); - mul_f256(t2, P2->x, t4); - mul_f256(t5, P1->z, t4); - mul_f256(t4, P2->y, t5); - - /* - * Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4). - * We need to test whether r is zero, so we will do some extra - * reduce. - */ - sub_f256(t2, t2, t1); - sub_f256(t4, t4, t3); - reduce_final_f256(t4); - ret = 0; - for (i = 0; i < 9; i ++) { - ret |= t4[i]; - } - ret = (ret | -ret) >> 31; - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5); - */ - square_f256(t7, t2); - mul_f256(t6, t1, t7); - mul_f256(t5, t7, t2); - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - */ - square_f256(P1->x, t4); - sub_f256(P1->x, P1->x, t5); - sub_f256(P1->x, P1->x, t6); - sub_f256(P1->x, P1->x, t6); - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - sub_f256(t6, t6, P1->x); - mul_f256(P1->y, t4, t6); - mul_f256(t1, t5, t3); - sub_f256(P1->y, P1->y, t1); - - /* - * Compute z3 = h*z1*z2. - */ - mul_f256(P1->z, P1->z, t2); - - return ret; -} - -/* - * Decode a P-256 point. This function does not support the point at - * infinity. Returned value is 0 if the point is invalid, 1 otherwise. - */ -static uint32_t -p256_decode(p256_jacobian *P, const void *src, size_t len) -{ - const unsigned char *buf; - uint32_t tx[9], ty[9], t1[9], t2[9]; - uint32_t bad; - int i; - - if (len != 65) { - return 0; - } - buf = src; - - /* - * First byte must be 0x04 (uncompressed format). We could support - * "hybrid format" (first byte is 0x06 or 0x07, and encodes the - * least significant bit of the Y coordinate), but it is explicitly - * forbidden by RFC 5480 (section 2.2). - */ - bad = NEQ(buf[0], 0x04); - - /* - * Decode the coordinates, and check that they are both lower - * than the modulus. - */ - tx[8] = be8_to_le30(tx, buf + 1, 32); - ty[8] = be8_to_le30(ty, buf + 33, 32); - bad |= reduce_final_f256(tx); - bad |= reduce_final_f256(ty); - - /* - * Check curve equation. - */ - square_f256(t1, tx); - mul_f256(t1, tx, t1); - square_f256(t2, ty); - sub_f256(t1, t1, tx); - sub_f256(t1, t1, tx); - sub_f256(t1, t1, tx); - add_f256(t1, t1, P256_B); - sub_f256(t1, t1, t2); - reduce_final_f256(t1); - for (i = 0; i < 9; i ++) { - bad |= t1[i]; - } - - /* - * Copy coordinates to the point structure. - */ - memcpy(P->x, tx, sizeof tx); - memcpy(P->y, ty, sizeof ty); - memset(P->z, 0, sizeof P->z); - P->z[0] = 1; - return NEQ(bad, 0) ^ 1; -} - -/* - * Encode a point into a buffer. This function assumes that the point is - * valid, in affine coordinates, and not the point at infinity. - */ -static void -p256_encode(void *dst, const p256_jacobian *P) -{ - unsigned char *buf; - - buf = dst; - buf[0] = 0x04; - le30_to_be8(buf + 1, 32, P->x); - le30_to_be8(buf + 33, 32, P->y); -} - -/* - * Multiply a curve point by an integer. The integer is assumed to be - * lower than the curve order, and the base point must not be the point - * at infinity. - */ -static void -p256_mul(p256_jacobian *P, const unsigned char *x, size_t xlen) -{ - /* - * qz is a flag that is initially 1, and remains equal to 1 - * as long as the point is the point at infinity. - * - * We use a 2-bit window to handle multiplier bits by pairs. - * The precomputed window really is the points P2 and P3. - */ - uint32_t qz; - p256_jacobian P2, P3, Q, T, U; - - /* - * Compute window values. - */ - P2 = *P; - p256_double(&P2); - P3 = *P; - p256_add(&P3, &P2); - - /* - * We start with Q = 0. We process multiplier bits 2 by 2. - */ - memset(&Q, 0, sizeof Q); - qz = 1; - while (xlen -- > 0) { - int k; - - for (k = 6; k >= 0; k -= 2) { - uint32_t bits; - uint32_t bnz; - - p256_double(&Q); - p256_double(&Q); - T = *P; - U = Q; - bits = (*x >> k) & (uint32_t)3; - bnz = NEQ(bits, 0); - CCOPY(EQ(bits, 2), &T, &P2, sizeof T); - CCOPY(EQ(bits, 3), &T, &P3, sizeof T); - p256_add(&U, &T); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - } - x ++; - } - *P = Q; -} - -/* - * Precomputed window: k*G points, where G is the curve generator, and k - * is an integer from 1 to 15 (inclusive). The X and Y coordinates of - * the point are encoded as 9 words of 30 bits each (little-endian - * order). - */ -static const uint32_t Gwin[15][18] = { - - { 0x1898C296, 0x1284E517, 0x1EB33A0F, 0x00DF604B, - 0x2440F277, 0x339B958E, 0x04247F8B, 0x347CB84B, - 0x00006B17, 0x37BF51F5, 0x2ED901A0, 0x3315ECEC, - 0x338CD5DA, 0x0F9E162B, 0x1FAD29F0, 0x27F9B8EE, - 0x10B8BF86, 0x00004FE3 }, - - { 0x07669978, 0x182D23F1, 0x3F21B35A, 0x225A789D, - 0x351AC3C0, 0x08E00C12, 0x34F7E8A5, 0x1EC62340, - 0x00007CF2, 0x227873D1, 0x3812DE74, 0x0E982299, - 0x1F6B798F, 0x3430DBBA, 0x366B1A7D, 0x2D040293, - 0x154436E3, 0x00000777 }, - - { 0x06E7FD6C, 0x2D05986F, 0x3ADA985F, 0x31ADC87B, - 0x0BF165E6, 0x1FBE5475, 0x30A44C8F, 0x3934698C, - 0x00005ECB, 0x227D5032, 0x29E6C49E, 0x04FB83D9, - 0x0AAC0D8E, 0x24A2ECD8, 0x2C1B3869, 0x0FF7E374, - 0x19031266, 0x00008734 }, - - { 0x2B030852, 0x024C0911, 0x05596EF5, 0x07F8B6DE, - 0x262BD003, 0x3779967B, 0x08FBBA02, 0x128D4CB4, - 0x0000E253, 0x184ED8C6, 0x310B08FC, 0x30EE0055, - 0x3F25B0FC, 0x062D764E, 0x3FB97F6A, 0x33CC719D, - 0x15D69318, 0x0000E0F1 }, - - { 0x03D033ED, 0x05552837, 0x35BE5242, 0x2320BF47, - 0x268FDFEF, 0x13215821, 0x140D2D78, 0x02DE9454, - 0x00005159, 0x3DA16DA4, 0x0742ED13, 0x0D80888D, - 0x004BC035, 0x0A79260D, 0x06FCDAFE, 0x2727D8AE, - 0x1F6A2412, 0x0000E0C1 }, - - { 0x3C2291A9, 0x1AC2ABA4, 0x3B215B4C, 0x131D037A, - 0x17DDE302, 0x0C90B2E2, 0x0602C92D, 0x05CA9DA9, - 0x0000B01A, 0x0FC77FE2, 0x35F1214E, 0x07E16BDF, - 0x003DDC07, 0x2703791C, 0x3038B7EE, 0x3DAD56FE, - 0x041D0C8D, 0x0000E85C }, - - { 0x3187B2A3, 0x0018A1C0, 0x00FEF5B3, 0x3E7E2E2A, - 0x01FB607E, 0x2CC199F0, 0x37B4625B, 0x0EDBE82F, - 0x00008E53, 0x01F400B4, 0x15786A1B, 0x3041B21C, - 0x31CD8CF2, 0x35900053, 0x1A7E0E9B, 0x318366D0, - 0x076F780C, 0x000073EB }, - - { 0x1B6FB393, 0x13767707, 0x3CE97DBB, 0x348E2603, - 0x354CADC1, 0x09D0B4EA, 0x1B053404, 0x1DE76FBA, - 0x000062D9, 0x0F09957E, 0x295029A8, 0x3E76A78D, - 0x3B547DAE, 0x27CEE0A2, 0x0575DC45, 0x1D8244FF, - 0x332F647A, 0x0000AD5A }, - - { 0x10949EE0, 0x1E7A292E, 0x06DF8B3D, 0x02B2E30B, - 0x31F8729E, 0x24E35475, 0x30B71878, 0x35EDBFB7, - 0x0000EA68, 0x0DD048FA, 0x21688929, 0x0DE823FE, - 0x1C53FAA9, 0x0EA0C84D, 0x052A592A, 0x1FCE7870, - 0x11325CB2, 0x00002A27 }, - - { 0x04C5723F, 0x30D81A50, 0x048306E4, 0x329B11C7, - 0x223FB545, 0x085347A8, 0x2993E591, 0x1B5ACA8E, - 0x0000CEF6, 0x04AF0773, 0x28D2EEA9, 0x2751EEEC, - 0x037B4A7F, 0x3B4C1059, 0x08F37674, 0x2AE906E1, - 0x18A88A6A, 0x00008786 }, - - { 0x34BC21D1, 0x0CCE474D, 0x15048BF4, 0x1D0BB409, - 0x021CDA16, 0x20DE76C3, 0x34C59063, 0x04EDE20E, - 0x00003ED1, 0x282A3740, 0x0BE3BBF3, 0x29889DAE, - 0x03413697, 0x34C68A09, 0x210EBE93, 0x0C8A224C, - 0x0826B331, 0x00009099 }, - - { 0x0624E3C4, 0x140317BA, 0x2F82C99D, 0x260C0A2C, - 0x25D55179, 0x194DCC83, 0x3D95E462, 0x356F6A05, - 0x0000741D, 0x0D4481D3, 0x2657FC8B, 0x1BA5CA71, - 0x3AE44B0D, 0x07B1548E, 0x0E0D5522, 0x05FDC567, - 0x2D1AA70E, 0x00000770 }, - - { 0x06072C01, 0x23857675, 0x1EAD58A9, 0x0B8A12D9, - 0x1EE2FC79, 0x0177CB61, 0x0495A618, 0x20DEB82B, - 0x0000177C, 0x2FC7BFD8, 0x310EEF8B, 0x1FB4DF39, - 0x3B8530E8, 0x0F4E7226, 0x0246B6D0, 0x2A558A24, - 0x163353AF, 0x000063BB }, - - { 0x24D2920B, 0x1C249DCC, 0x2069C5E5, 0x09AB2F9E, - 0x36DF3CF1, 0x1991FD0C, 0x062B97A7, 0x1E80070E, - 0x000054E7, 0x20D0B375, 0x2E9F20BD, 0x35090081, - 0x1C7A9DDC, 0x22E7C371, 0x087E3016, 0x03175421, - 0x3C6ECA7D, 0x0000F599 }, - - { 0x259B9D5F, 0x0D9A318F, 0x23A0EF16, 0x00EBE4B7, - 0x088265AE, 0x2CDE2666, 0x2BAE7ADF, 0x1371A5C6, - 0x0000F045, 0x0D034F36, 0x1F967378, 0x1B5FA3F4, - 0x0EC8739D, 0x1643E62A, 0x1653947E, 0x22D1F4E6, - 0x0FB8D64B, 0x0000B5B9 } -}; - -/* - * Lookup one of the Gwin[] values, by index. This is constant-time. - */ -static void -lookup_Gwin(p256_jacobian *T, uint32_t idx) -{ - uint32_t xy[18]; - uint32_t k; - size_t u; - - memset(xy, 0, sizeof xy); - for (k = 0; k < 15; k ++) { - uint32_t m; - - m = -EQ(idx, k + 1); - for (u = 0; u < 18; u ++) { - xy[u] |= m & Gwin[k][u]; - } - } - memcpy(T->x, &xy[0], sizeof T->x); - memcpy(T->y, &xy[9], sizeof T->y); - memset(T->z, 0, sizeof T->z); - T->z[0] = 1; -} - -/* - * Multiply the generator by an integer. The integer is assumed non-zero - * and lower than the curve order. - */ -static void -p256_mulgen(p256_jacobian *P, const unsigned char *x, size_t xlen) -{ - /* - * qz is a flag that is initially 1, and remains equal to 1 - * as long as the point is the point at infinity. - * - * We use a 4-bit window to handle multiplier bits by groups - * of 4. The precomputed window is constant static data, with - * points in affine coordinates; we use a constant-time lookup. - */ - p256_jacobian Q; - uint32_t qz; - - memset(&Q, 0, sizeof Q); - qz = 1; - while (xlen -- > 0) { - int k; - unsigned bx; - - bx = *x ++; - for (k = 0; k < 2; k ++) { - uint32_t bits; - uint32_t bnz; - p256_jacobian T, U; - - p256_double(&Q); - p256_double(&Q); - p256_double(&Q); - p256_double(&Q); - bits = (bx >> 4) & 0x0F; - bnz = NEQ(bits, 0); - lookup_Gwin(&T, bits); - U = Q; - p256_add_mixed(&U, &T); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - bx <<= 4; - } - } - *P = Q; -} - -static const unsigned char P256_G[] = { - 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, - 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, - 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, - 0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, - 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B, - 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, - 0x68, 0x37, 0xBF, 0x51, 0xF5 -}; - -static const unsigned char P256_N[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, - 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, - 0x25, 0x51 -}; - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - (void)curve; - *len = sizeof P256_G; - return P256_G; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - (void)curve; - *len = sizeof P256_N; - return P256_N; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - (void)curve; - *len = 32; - return 1; -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *x, size_t xlen, int curve) -{ - uint32_t r; - p256_jacobian P; - - (void)curve; - r = p256_decode(&P, G, Glen); - p256_mul(&P, x, xlen); - if (Glen >= 65) { - p256_to_affine(&P); - p256_encode(G, &P); - } - return r; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - p256_jacobian P; - - (void)curve; - p256_mulgen(&P, x, xlen); - p256_to_affine(&P); - p256_encode(R, &P); - return 65; - - /* - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; - */ -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - p256_jacobian P, Q; - uint32_t r, t, z; - int i; - - (void)curve; - r = p256_decode(&P, A, len); - p256_mul(&P, x, xlen); - if (B == NULL) { - p256_mulgen(&Q, y, ylen); - } else { - r &= p256_decode(&Q, B, len); - p256_mul(&Q, y, ylen); - } - - /* - * The final addition may fail in case both points are equal. - */ - t = p256_add(&P, &Q); - reduce_final_f256(P.z); - z = 0; - for (i = 0; i < 9; i ++) { - z |= P.z[i]; - } - z = EQ(z, 0); - p256_double(&Q); - - /* - * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we - * have the following: - * - * z = 0, t = 0 return P (normal addition) - * z = 0, t = 1 return P (normal addition) - * z = 1, t = 0 return Q (a 'double' case) - * z = 1, t = 1 report an error (P+Q = 0) - */ - CCOPY(z & ~t, &P, &Q, sizeof Q); - p256_to_affine(&P); - p256_encode(A, &P); - r &= ~(z & t); - return r; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_p256_m31 = { - (uint32_t)0x00800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_prime_i15.c b/src/tls/bearssl/ec_prime_i15.c deleted file mode 100644 index bfb5e6b55..000000000 --- a/src/tls/bearssl/ec_prime_i15.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Parameters for supported curves: - * - field modulus p - * - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p) - * - b*R mod p (b is the second curve equation parameter) - */ - -static const uint16_t P256_P[] = { - 0x0111, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF, - 0x7FFF, 0x0001 -}; - -static const uint16_t P256_R2[] = { - 0x0111, - 0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF, - 0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF, - 0x4FFF, 0x0000 -}; - -static const uint16_t P256_B[] = { - 0x0111, - 0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993, - 0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16, - 0x0187, 0x0000 -}; - -static const uint16_t P384_P[] = { - 0x0199, - 0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF, - 0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x01FF -}; - -static const uint16_t P384_R2[] = { - 0x0199, - 0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010, - 0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000, - 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000 -}; - -static const uint16_t P384_B[] = { - 0x0199, - 0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB, - 0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2, - 0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09, - 0x0452, 0x0084 -}; - -static const uint16_t P521_P[] = { - 0x022B, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, - 0x7FFF, 0x7FFF, 0x07FF -}; - -static const uint16_t P521_R2[] = { - 0x022B, - 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000 -}; - -static const uint16_t P521_B[] = { - 0x022B, - 0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC, - 0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F, - 0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD, - 0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4, - 0x1618, 0x27D7, 0x0465 -}; - -typedef struct { - const uint16_t *p; - const uint16_t *b; - const uint16_t *R2; - uint16_t p0i; - size_t point_len; -} curve_params; - -static inline const curve_params * -id_to_curve(int curve) -{ - static const curve_params pp[] = { - { P256_P, P256_B, P256_R2, 0x0001, 65 }, - { P384_P, P384_B, P384_R2, 0x0001, 97 }, - { P521_P, P521_B, P521_R2, 0x0001, 133 } - }; - - return &pp[curve - BR_EC_secp256r1]; -} - -#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) - -/* - * Type for a point in Jacobian coordinates: - * -- three values, x, y and z, in Montgomery representation - * -- affine coordinates are X = x / z^2 and Y = y / z^3 - * -- for the point at infinity, z = 0 - */ -typedef struct { - uint16_t c[3][I15_LEN]; -} jacobian; - -/* - * We use a custom interpreter that uses a dozen registers, and - * only six operations: - * MSET(d, a) copy a into d - * MADD(d, a) d = d+a (modular) - * MSUB(d, a) d = d-a (modular) - * MMUL(d, a, b) d = a*b (Montgomery multiplication) - * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers - * MTZ(d) clear return value if d = 0 - * Destination of MMUL (d) must be distinct from operands (a and b). - * There is no such constraint for MSUB and MADD. - * - * Registers include the operand coordinates, and temporaries. - */ -#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4)) -#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4)) -#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4)) -#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b)) -#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b)) -#define MTZ(d) (0x5000 + ((d) << 8)) -#define ENDCODE 0 - -/* - * Registers for the input operands. - */ -#define P1x 0 -#define P1y 1 -#define P1z 2 -#define P2x 3 -#define P2y 4 -#define P2z 5 - -/* - * Alternate names for the first input operand. - */ -#define Px 0 -#define Py 1 -#define Pz 2 - -/* - * Temporaries. - */ -#define t1 6 -#define t2 7 -#define t3 8 -#define t4 9 -#define t5 10 -#define t6 11 -#define t7 12 - -/* - * Extra scratch registers available when there is no second operand (e.g. - * for "double" and "affine"). - */ -#define t8 3 -#define t9 4 -#define t10 5 - -/* - * Doubling formulas are: - * - * s = 4*x*y^2 - * m = 3*(x + z^2)*(x - z^2) - * x' = m^2 - 2*s - * y' = m*(s - x') - 8*y^4 - * z' = 2*y*z - * - * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it - * should. This case should not happen anyway, because our curves have - * prime order, and thus do not contain any point of order 2. - * - * If P is infinity (z = 0), then again the formulas yield infinity, - * which is correct. Thus, this code works for all points. - * - * Cost: 8 multiplications - */ -static const uint16_t code_double[] = { - /* - * Compute z^2 (in t1). - */ - MMUL(t1, Pz, Pz), - - /* - * Compute x-z^2 (in t2) and then x+z^2 (in t1). - */ - MSET(t2, Px), - MSUB(t2, t1), - MADD(t1, Px), - - /* - * Compute m = 3*(x+z^2)*(x-z^2) (in t1). - */ - MMUL(t3, t1, t2), - MSET(t1, t3), - MADD(t1, t3), - MADD(t1, t3), - - /* - * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3). - */ - MMUL(t3, Py, Py), - MADD(t3, t3), - MMUL(t2, Px, t3), - MADD(t2, t2), - - /* - * Compute x' = m^2 - 2*s. - */ - MMUL(Px, t1, t1), - MSUB(Px, t2), - MSUB(Px, t2), - - /* - * Compute z' = 2*y*z. - */ - MMUL(t4, Py, Pz), - MSET(Pz, t4), - MADD(Pz, t4), - - /* - * Compute y' = m*(s - x') - 8*y^4. Note that we already have - * 2*y^2 in t3. - */ - MSUB(t2, Px), - MMUL(Py, t1, t2), - MMUL(t4, t3, t3), - MSUB(Py, t4), - MSUB(Py, t4), - - ENDCODE -}; - -/* - * Addtions formulas are: - * - * u1 = x1 * z2^2 - * u2 = x2 * z1^2 - * s1 = y1 * z2^3 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 * z2 - * - * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that - * z3 == 0, so the result is correct. - * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is - * not correct. - * h == 0 only if u1 == u2; this happens in two cases: - * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2 - * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity) - * - * Thus, the following situations are not handled correctly: - * -- P1 = 0 and P2 != 0 - * -- P1 != 0 and P2 = 0 - * -- P1 = P2 - * All other cases are properly computed. However, even in "incorrect" - * situations, the three coordinates still are properly formed field - * elements. - * - * The returned flag is cleared if r == 0. This happens in the following - * cases: - * -- Both points are on the same horizontal line (same Y coordinate). - * -- Both points are infinity. - * -- One point is infinity and the other is on line Y = 0. - * The third case cannot happen with our curves (there is no valid point - * on line Y = 0 since that would be a point of order 2). If the two - * source points are non-infinity, then remains only the case where the - * two points are on the same horizontal line. - * - * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and - * P2 != 0: - * -- If the returned value is not the point at infinity, then it was properly - * computed. - * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result - * is indeed the point at infinity. - * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should - * use the 'double' code. - * - * Cost: 16 multiplications - */ -static const uint16_t code_add[] = { - /* - * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). - */ - MMUL(t3, P2z, P2z), - MMUL(t1, P1x, t3), - MMUL(t4, P2z, t3), - MMUL(t3, P1y, t4), - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - MMUL(t4, P1z, P1z), - MMUL(t2, P2x, t4), - MMUL(t5, P1z, t4), - MMUL(t4, P2y, t5), - - /* - * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4). - */ - MSUB(t2, t1), - MSUB(t4, t3), - - /* - * Report cases where r = 0 through the returned flag. - */ - MTZ(t4), - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5). - */ - MMUL(t7, t2, t2), - MMUL(t6, t1, t7), - MMUL(t5, t7, t2), - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - * t1 and t7 can be used as scratch registers. - */ - MMUL(P1x, t4, t4), - MSUB(P1x, t5), - MSUB(P1x, t6), - MSUB(P1x, t6), - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - MSUB(t6, P1x), - MMUL(P1y, t4, t6), - MMUL(t1, t5, t3), - MSUB(P1y, t1), - - /* - * Compute z3 = h*z1*z2. - */ - MMUL(t1, P1z, P2z), - MMUL(P1z, t1, t2), - - ENDCODE -}; - -/* - * Check that the point is on the curve. This code snippet assumes the - * following conventions: - * -- Coordinates x and y have been freshly decoded in P1 (but not - * converted to Montgomery coordinates yet). - * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1. - */ -static const uint16_t code_check[] = { - - /* Convert x and y to Montgomery representation. */ - MMUL(t1, P1x, P2x), - MMUL(t2, P1y, P2x), - MSET(P1x, t1), - MSET(P1y, t2), - - /* Compute x^3 in t1. */ - MMUL(t2, P1x, P1x), - MMUL(t1, P1x, t2), - - /* Subtract 3*x from t1. */ - MSUB(t1, P1x), - MSUB(t1, P1x), - MSUB(t1, P1x), - - /* Add b. */ - MADD(t1, P2y), - - /* Compute y^2 in t2. */ - MMUL(t2, P1y, P1y), - - /* Compare y^2 with x^3 - 3*x + b; they must match. */ - MSUB(t1, t2), - MTZ(t1), - - /* Set z to 1 (in Montgomery representation). */ - MMUL(P1z, P2x, P2z), - - ENDCODE -}; - -/* - * Conversion back to affine coordinates. This code snippet assumes that - * the z coordinate of P2 is set to 1 (not in Montgomery representation). - */ -static const uint16_t code_affine[] = { - - /* Save z*R in t1. */ - MSET(t1, P1z), - - /* Compute z^3 in t2. */ - MMUL(t2, P1z, P1z), - MMUL(t3, P1z, t2), - MMUL(t2, t3, P2z), - - /* Invert to (1/z^3) in t2. */ - MINV(t2, t3, t4), - - /* Compute y. */ - MSET(t3, P1y), - MMUL(P1y, t2, t3), - - /* Compute (1/z^2) in t3. */ - MMUL(t3, t2, t1), - - /* Compute x. */ - MSET(t2, P1x), - MMUL(P1x, t2, t3), - - ENDCODE -}; - -static uint32_t -run_code(jacobian *P1, const jacobian *P2, - const curve_params *cc, const uint16_t *code) -{ - uint32_t r; - uint16_t t[13][I15_LEN]; - size_t u; - - r = 1; - - /* - * Copy the two operands in the dedicated registers. - */ - memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t)); - memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t)); - - /* - * Run formulas. - */ - for (u = 0;; u ++) { - unsigned op, d, a, b; - - op = code[u]; - if (op == 0) { - break; - } - d = (op >> 8) & 0x0F; - a = (op >> 4) & 0x0F; - b = op & 0x0F; - op >>= 12; - switch (op) { - uint32_t ctl; - size_t plen; - unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; - - case 0: - memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t)); - break; - case 1: - ctl = br_i15_add(t[d], t[a], 1); - ctl |= NOT(br_i15_sub(t[d], cc->p, 0)); - br_i15_sub(t[d], cc->p, ctl); - break; - case 2: - br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1)); - break; - case 3: - br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i); - break; - case 4: - plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; - br_i15_encode(tp, plen, cc->p); - tp[plen - 1] -= 2; - br_i15_modpow(t[d], tp, plen, - cc->p, cc->p0i, t[a], t[b]); - break; - default: - r &= ~br_i15_iszero(t[d]); - break; - } - } - - /* - * Copy back result. - */ - memcpy(P1->c, t[P1x], 3 * I15_LEN * sizeof(uint16_t)); - return r; -} - -static void -set_one(uint16_t *x, const uint16_t *p) -{ - size_t plen; - - plen = (p[0] + 31) >> 4; - memset(x, 0, plen * sizeof *x); - x[0] = p[0]; - x[1] = 0x0001; -} - -static void -point_zero(jacobian *P, const curve_params *cc) -{ - memset(P, 0, sizeof *P); - P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; -} - -static inline void -point_double(jacobian *P, const curve_params *cc) -{ - run_code(P, P, cc, code_double); -} - -static inline uint32_t -point_add(jacobian *P1, const jacobian *P2, const curve_params *cc) -{ - return run_code(P1, P2, cc, code_add); -} - -static void -point_mul(jacobian *P, const unsigned char *x, size_t xlen, - const curve_params *cc) -{ - /* - * We do a simple double-and-add ladder with a 2-bit window - * to make only one add every two doublings. We thus first - * precompute 2P and 3P in some local buffers. - * - * We always perform two doublings and one addition; the - * addition is with P, 2P and 3P and is done in a temporary - * array. - * - * The addition code cannot handle cases where one of the - * operands is infinity, which is the case at the start of the - * ladder. We therefore need to maintain a flag that controls - * this situation. - */ - uint32_t qz; - jacobian P2, P3, Q, T, U; - - memcpy(&P2, P, sizeof P2); - point_double(&P2, cc); - memcpy(&P3, P, sizeof P3); - point_add(&P3, &P2, cc); - - point_zero(&Q, cc); - qz = 1; - while (xlen -- > 0) { - int k; - - for (k = 6; k >= 0; k -= 2) { - uint32_t bits; - uint32_t bnz; - - point_double(&Q, cc); - point_double(&Q, cc); - memcpy(&T, P, sizeof T); - memcpy(&U, &Q, sizeof U); - bits = (*x >> k) & (uint32_t)3; - bnz = NEQ(bits, 0); - CCOPY(EQ(bits, 2), &T, &P2, sizeof T); - CCOPY(EQ(bits, 3), &T, &P3, sizeof T); - point_add(&U, &T, cc); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - } - x ++; - } - memcpy(P, &Q, sizeof Q); -} - -/* - * Decode point into Jacobian coordinates. This function does not support - * the point at infinity. If the point is invalid then this returns 0, but - * the coordinates are still set to properly formed field elements. - */ -static uint32_t -point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) -{ - /* - * Points must use uncompressed format: - * -- first byte is 0x04; - * -- coordinates X and Y use unsigned big-endian, with the same - * length as the field modulus. - * - * We don't support hybrid format (uncompressed, but first byte - * has value 0x06 or 0x07, depending on the least significant bit - * of Y) because it is rather useless, and explicitly forbidden - * by PKIX (RFC 5480, section 2.2). - * - * We don't support compressed format either, because it is not - * much used in practice (there are or were patent-related - * concerns about point compression, which explains the lack of - * generalised support). Also, point compression support would - * need a bit more code. - */ - const unsigned char *buf; - size_t plen, zlen; - uint32_t r; - jacobian Q; - - buf = src; - point_zero(P, cc); - plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; - if (len != 1 + (plen << 1)) { - return 0; - } - r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p); - r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p); - - /* - * Check first byte. - */ - r &= EQ(buf[0], 0x04); - /* obsolete - r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06) - & ~(uint32_t)(buf[0] ^ buf[plen << 1])); - */ - - /* - * Convert coordinates and check that the point is valid. - */ - zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t); - memcpy(Q.c[0], cc->R2, zlen); - memcpy(Q.c[1], cc->b, zlen); - set_one(Q.c[2], cc->p); - r &= ~run_code(P, &Q, cc, code_check); - return r; -} - -/* - * Encode a point. This method assumes that the point is correct and is - * not the point at infinity. Encoded size is always 1+2*plen, where - * plen is the field modulus length, in bytes. - */ -static void -point_encode(void *dst, const jacobian *P, const curve_params *cc) -{ - unsigned char *buf; - size_t plen; - jacobian Q, T; - - buf = dst; - plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3; - buf[0] = 0x04; - memcpy(&Q, P, sizeof *P); - set_one(T.c[2], cc->p); - run_code(&Q, &T, cc, code_affine); - br_i15_encode(buf + 1, plen, Q.c[0]); - br_i15_encode(buf + 1 + plen, plen, Q.c[1]); -} - -static const br_ec_curve_def * -id_to_curve_def(int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return &br_secp256r1; - case BR_EC_secp384r1: - return &br_secp384r1; - case BR_EC_secp521r1: - return &br_secp521r1; - } - return NULL; -} - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - const br_ec_curve_def *cd; - - cd = id_to_curve_def(curve); - *len = cd->generator_len; - return cd->generator; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - const br_ec_curve_def *cd; - - cd = id_to_curve_def(curve); - *len = cd->order_len; - return cd->order; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - api_generator(curve, len); - *len >>= 1; - return 1; -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *x, size_t xlen, int curve) -{ - uint32_t r; - const curve_params *cc; - jacobian P; - - cc = id_to_curve(curve); - r = point_decode(&P, G, Glen, cc); - point_mul(&P, x, xlen, cc); - if (Glen == cc->point_len) { - point_encode(G, &P, cc); - } - return r; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - uint32_t r, t, z; - const curve_params *cc; - jacobian P, Q; - - /* - * TODO: see about merging the two ladders. Right now, we do - * two independent point multiplications, which is a bit - * wasteful of CPU resources (but yields short code). - */ - - cc = id_to_curve(curve); - r = point_decode(&P, A, len, cc); - if (B == NULL) { - size_t Glen; - - B = api_generator(curve, &Glen); - } - r &= point_decode(&Q, B, len, cc); - point_mul(&P, x, xlen, cc); - point_mul(&Q, y, ylen, cc); - - /* - * We want to compute P+Q. Since the base points A and B are distinct - * from infinity, and the multipliers are non-zero and lower than the - * curve order, then we know that P and Q are non-infinity. This - * leaves two special situations to test for: - * -- If P = Q then we must use point_double(). - * -- If P+Q = 0 then we must report an error. - */ - t = point_add(&P, &Q, cc); - point_double(&Q, cc); - z = br_i15_iszero(P.c[2]); - - /* - * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we - * have the following: - * - * z = 0, t = 0 return P (normal addition) - * z = 0, t = 1 return P (normal addition) - * z = 1, t = 0 return Q (a 'double' case) - * z = 1, t = 1 report an error (P+Q = 0) - */ - CCOPY(z & ~t, &P, &Q, sizeof Q); - point_encode(A, &P, cc); - r &= ~(z & t); - - return r; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_prime_i15 = { - (uint32_t)0x03800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_prime_i31.c b/src/tls/bearssl/ec_prime_i31.c deleted file mode 100644 index 783dbf96e..000000000 --- a/src/tls/bearssl/ec_prime_i31.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Parameters for supported curves (field modulus, and 'b' equation - * parameter; both values use the 'i31' format, and 'b' is in Montgomery - * representation). - */ - -static const uint32_t P256_P[] = { - 0x00000108, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007, - 0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80, - 0x000000FF -}; - -static const uint32_t P256_R2[] = { - 0x00000108, - 0x00014000, 0x00018000, 0x00000000, 0x7FF40000, - 0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF, - 0x00000000 -}; - -static const uint32_t P256_B[] = { - 0x00000108, - 0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA, - 0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D, - 0x0000000E -}; - -static const uint32_t P384_P[] = { - 0x0000018C, - 0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8, - 0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x00000FFF -}; - -static const uint32_t P384_R2[] = { - 0x0000018C, - 0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF, - 0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF, - 0x00008000, 0x00008000, 0x00000000, 0x00000000, - 0x00000000 -}; - -static const uint32_t P384_B[] = { - 0x0000018C, - 0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C, - 0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B, - 0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE, - 0x000008A5 -}; - -static const uint32_t P521_P[] = { - 0x00000219, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, - 0x01FFFFFF -}; - -static const uint32_t P521_R2[] = { - 0x00000219, - 0x00001000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000 -}; - -static const uint32_t P521_B[] = { - 0x00000219, - 0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A, - 0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F, - 0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366, - 0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393, - 0x00654FAE -}; - -typedef struct { - const uint32_t *p; - const uint32_t *b; - const uint32_t *R2; - uint32_t p0i; -} curve_params; - -static inline const curve_params * -id_to_curve(int curve) -{ - static const curve_params pp[] = { - { P256_P, P256_B, P256_R2, 0x00000001 }, - { P384_P, P384_B, P384_R2, 0x00000001 }, - { P521_P, P521_B, P521_R2, 0x00000001 } - }; - - return &pp[curve - BR_EC_secp256r1]; -} - -#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) - -/* - * Type for a point in Jacobian coordinates: - * -- three values, x, y and z, in Montgomery representation - * -- affine coordinates are X = x / z^2 and Y = y / z^3 - * -- for the point at infinity, z = 0 - */ -typedef struct { - uint32_t c[3][I31_LEN]; -} jacobian; - -/* - * We use a custom interpreter that uses a dozen registers, and - * only six operations: - * MSET(d, a) copy a into d - * MADD(d, a) d = d+a (modular) - * MSUB(d, a) d = d-a (modular) - * MMUL(d, a, b) d = a*b (Montgomery multiplication) - * MINV(d, a, b) invert d modulo p; a and b are used as scratch registers - * MTZ(d) clear return value if d = 0 - * Destination of MMUL (d) must be distinct from operands (a and b). - * There is no such constraint for MSUB and MADD. - * - * Registers include the operand coordinates, and temporaries. - */ -#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4)) -#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4)) -#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4)) -#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b)) -#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b)) -#define MTZ(d) (0x5000 + ((d) << 8)) -#define ENDCODE 0 - -/* - * Registers for the input operands. - */ -#define P1x 0 -#define P1y 1 -#define P1z 2 -#define P2x 3 -#define P2y 4 -#define P2z 5 - -/* - * Alternate names for the first input operand. - */ -#define Px 0 -#define Py 1 -#define Pz 2 - -/* - * Temporaries. - */ -#define t1 6 -#define t2 7 -#define t3 8 -#define t4 9 -#define t5 10 -#define t6 11 -#define t7 12 - -/* - * Extra scratch registers available when there is no second operand (e.g. - * for "double" and "affine"). - */ -#define t8 3 -#define t9 4 -#define t10 5 - -/* - * Doubling formulas are: - * - * s = 4*x*y^2 - * m = 3*(x + z^2)*(x - z^2) - * x' = m^2 - 2*s - * y' = m*(s - x') - 8*y^4 - * z' = 2*y*z - * - * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it - * should. This case should not happen anyway, because our curves have - * prime order, and thus do not contain any point of order 2. - * - * If P is infinity (z = 0), then again the formulas yield infinity, - * which is correct. Thus, this code works for all points. - * - * Cost: 8 multiplications - */ -static const uint16_t code_double[] = { - /* - * Compute z^2 (in t1). - */ - MMUL(t1, Pz, Pz), - - /* - * Compute x-z^2 (in t2) and then x+z^2 (in t1). - */ - MSET(t2, Px), - MSUB(t2, t1), - MADD(t1, Px), - - /* - * Compute m = 3*(x+z^2)*(x-z^2) (in t1). - */ - MMUL(t3, t1, t2), - MSET(t1, t3), - MADD(t1, t3), - MADD(t1, t3), - - /* - * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3). - */ - MMUL(t3, Py, Py), - MADD(t3, t3), - MMUL(t2, Px, t3), - MADD(t2, t2), - - /* - * Compute x' = m^2 - 2*s. - */ - MMUL(Px, t1, t1), - MSUB(Px, t2), - MSUB(Px, t2), - - /* - * Compute z' = 2*y*z. - */ - MMUL(t4, Py, Pz), - MSET(Pz, t4), - MADD(Pz, t4), - - /* - * Compute y' = m*(s - x') - 8*y^4. Note that we already have - * 2*y^2 in t3. - */ - MSUB(t2, Px), - MMUL(Py, t1, t2), - MMUL(t4, t3, t3), - MSUB(Py, t4), - MSUB(Py, t4), - - ENDCODE -}; - -/* - * Addtions formulas are: - * - * u1 = x1 * z2^2 - * u2 = x2 * z1^2 - * s1 = y1 * z2^3 - * s2 = y2 * z1^3 - * h = u2 - u1 - * r = s2 - s1 - * x3 = r^2 - h^3 - 2 * u1 * h^2 - * y3 = r * (u1 * h^2 - x3) - s1 * h^3 - * z3 = h * z1 * z2 - * - * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that - * z3 == 0, so the result is correct. - * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is - * not correct. - * h == 0 only if u1 == u2; this happens in two cases: - * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2 - * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity) - * - * Thus, the following situations are not handled correctly: - * -- P1 = 0 and P2 != 0 - * -- P1 != 0 and P2 = 0 - * -- P1 = P2 - * All other cases are properly computed. However, even in "incorrect" - * situations, the three coordinates still are properly formed field - * elements. - * - * The returned flag is cleared if r == 0. This happens in the following - * cases: - * -- Both points are on the same horizontal line (same Y coordinate). - * -- Both points are infinity. - * -- One point is infinity and the other is on line Y = 0. - * The third case cannot happen with our curves (there is no valid point - * on line Y = 0 since that would be a point of order 2). If the two - * source points are non-infinity, then remains only the case where the - * two points are on the same horizontal line. - * - * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and - * P2 != 0: - * -- If the returned value is not the point at infinity, then it was properly - * computed. - * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result - * is indeed the point at infinity. - * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should - * use the 'double' code. - * - * Cost: 16 multiplications - */ -static const uint16_t code_add[] = { - /* - * Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3). - */ - MMUL(t3, P2z, P2z), - MMUL(t1, P1x, t3), - MMUL(t4, P2z, t3), - MMUL(t3, P1y, t4), - - /* - * Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4). - */ - MMUL(t4, P1z, P1z), - MMUL(t2, P2x, t4), - MMUL(t5, P1z, t4), - MMUL(t4, P2y, t5), - - /* - * Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4). - */ - MSUB(t2, t1), - MSUB(t4, t3), - - /* - * Report cases where r = 0 through the returned flag. - */ - MTZ(t4), - - /* - * Compute u1*h^2 (in t6) and h^3 (in t5). - */ - MMUL(t7, t2, t2), - MMUL(t6, t1, t7), - MMUL(t5, t7, t2), - - /* - * Compute x3 = r^2 - h^3 - 2*u1*h^2. - * t1 and t7 can be used as scratch registers. - */ - MMUL(P1x, t4, t4), - MSUB(P1x, t5), - MSUB(P1x, t6), - MSUB(P1x, t6), - - /* - * Compute y3 = r*(u1*h^2 - x3) - s1*h^3. - */ - MSUB(t6, P1x), - MMUL(P1y, t4, t6), - MMUL(t1, t5, t3), - MSUB(P1y, t1), - - /* - * Compute z3 = h*z1*z2. - */ - MMUL(t1, P1z, P2z), - MMUL(P1z, t1, t2), - - ENDCODE -}; - -/* - * Check that the point is on the curve. This code snippet assumes the - * following conventions: - * -- Coordinates x and y have been freshly decoded in P1 (but not - * converted to Montgomery coordinates yet). - * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1. - */ -static const uint16_t code_check[] = { - - /* Convert x and y to Montgomery representation. */ - MMUL(t1, P1x, P2x), - MMUL(t2, P1y, P2x), - MSET(P1x, t1), - MSET(P1y, t2), - - /* Compute x^3 in t1. */ - MMUL(t2, P1x, P1x), - MMUL(t1, P1x, t2), - - /* Subtract 3*x from t1. */ - MSUB(t1, P1x), - MSUB(t1, P1x), - MSUB(t1, P1x), - - /* Add b. */ - MADD(t1, P2y), - - /* Compute y^2 in t2. */ - MMUL(t2, P1y, P1y), - - /* Compare y^2 with x^3 - 3*x + b; they must match. */ - MSUB(t1, t2), - MTZ(t1), - - /* Set z to 1 (in Montgomery representation). */ - MMUL(P1z, P2x, P2z), - - ENDCODE -}; - -/* - * Conversion back to affine coordinates. This code snippet assumes that - * the z coordinate of P2 is set to 1 (not in Montgomery representation). - */ -static const uint16_t code_affine[] = { - - /* Save z*R in t1. */ - MSET(t1, P1z), - - /* Compute z^3 in t2. */ - MMUL(t2, P1z, P1z), - MMUL(t3, P1z, t2), - MMUL(t2, t3, P2z), - - /* Invert to (1/z^3) in t2. */ - MINV(t2, t3, t4), - - /* Compute y. */ - MSET(t3, P1y), - MMUL(P1y, t2, t3), - - /* Compute (1/z^2) in t3. */ - MMUL(t3, t2, t1), - - /* Compute x. */ - MSET(t2, P1x), - MMUL(P1x, t2, t3), - - ENDCODE -}; - -static uint32_t -run_code(jacobian *P1, const jacobian *P2, - const curve_params *cc, const uint16_t *code) -{ - uint32_t r; - uint32_t t[13][I31_LEN]; - size_t u; - - r = 1; - - /* - * Copy the two operands in the dedicated registers. - */ - memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t)); - memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t)); - - /* - * Run formulas. - */ - for (u = 0;; u ++) { - unsigned op, d, a, b; - - op = code[u]; - if (op == 0) { - break; - } - d = (op >> 8) & 0x0F; - a = (op >> 4) & 0x0F; - b = op & 0x0F; - op >>= 12; - switch (op) { - uint32_t ctl; - size_t plen; - unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3]; - - case 0: - memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t)); - break; - case 1: - ctl = br_i31_add(t[d], t[a], 1); - ctl |= NOT(br_i31_sub(t[d], cc->p, 0)); - br_i31_sub(t[d], cc->p, ctl); - break; - case 2: - br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1)); - break; - case 3: - br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i); - break; - case 4: - plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3; - br_i31_encode(tp, plen, cc->p); - tp[plen - 1] -= 2; - br_i31_modpow(t[d], tp, plen, - cc->p, cc->p0i, t[a], t[b]); - break; - default: - r &= ~br_i31_iszero(t[d]); - break; - } - } - - /* - * Copy back result. - */ - memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t)); - return r; -} - -static void -set_one(uint32_t *x, const uint32_t *p) -{ - size_t plen; - - plen = (p[0] + 63) >> 5; - memset(x, 0, plen * sizeof *x); - x[0] = p[0]; - x[1] = 0x00000001; -} - -static void -point_zero(jacobian *P, const curve_params *cc) -{ - memset(P, 0, sizeof *P); - P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0]; -} - -static inline void -point_double(jacobian *P, const curve_params *cc) -{ - run_code(P, P, cc, code_double); -} - -static inline uint32_t -point_add(jacobian *P1, const jacobian *P2, const curve_params *cc) -{ - return run_code(P1, P2, cc, code_add); -} - -static void -point_mul(jacobian *P, const unsigned char *x, size_t xlen, - const curve_params *cc) -{ - /* - * We do a simple double-and-add ladder with a 2-bit window - * to make only one add every two doublings. We thus first - * precompute 2P and 3P in some local buffers. - * - * We always perform two doublings and one addition; the - * addition is with P, 2P and 3P and is done in a temporary - * array. - * - * The addition code cannot handle cases where one of the - * operands is infinity, which is the case at the start of the - * ladder. We therefore need to maintain a flag that controls - * this situation. - */ - uint32_t qz; - jacobian P2, P3, Q, T, U; - - memcpy(&P2, P, sizeof P2); - point_double(&P2, cc); - memcpy(&P3, P, sizeof P3); - point_add(&P3, &P2, cc); - - point_zero(&Q, cc); - qz = 1; - while (xlen -- > 0) { - int k; - - for (k = 6; k >= 0; k -= 2) { - uint32_t bits; - uint32_t bnz; - - point_double(&Q, cc); - point_double(&Q, cc); - memcpy(&T, P, sizeof T); - memcpy(&U, &Q, sizeof U); - bits = (*x >> k) & (uint32_t)3; - bnz = NEQ(bits, 0); - CCOPY(EQ(bits, 2), &T, &P2, sizeof T); - CCOPY(EQ(bits, 3), &T, &P3, sizeof T); - point_add(&U, &T, cc); - CCOPY(bnz & qz, &Q, &T, sizeof Q); - CCOPY(bnz & ~qz, &Q, &U, sizeof Q); - qz &= ~bnz; - } - x ++; - } - memcpy(P, &Q, sizeof Q); -} - -/* - * Decode point into Jacobian coordinates. This function does not support - * the point at infinity. If the point is invalid then this returns 0, but - * the coordinates are still set to properly formed field elements. - */ -static uint32_t -point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc) -{ - /* - * Points must use uncompressed format: - * -- first byte is 0x04; - * -- coordinates X and Y use unsigned big-endian, with the same - * length as the field modulus. - * - * We don't support hybrid format (uncompressed, but first byte - * has value 0x06 or 0x07, depending on the least significant bit - * of Y) because it is rather useless, and explicitly forbidden - * by PKIX (RFC 5480, section 2.2). - * - * We don't support compressed format either, because it is not - * much used in practice (there are or were patent-related - * concerns about point compression, which explains the lack of - * generalised support). Also, point compression support would - * need a bit more code. - */ - const unsigned char *buf; - size_t plen, zlen; - uint32_t r; - jacobian Q; - - buf = src; - point_zero(P, cc); - plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3; - if (len != 1 + (plen << 1)) { - return 0; - } - r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p); - r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p); - - /* - * Check first byte. - */ - r &= EQ(buf[0], 0x04); - /* obsolete - r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06) - & ~(uint32_t)(buf[0] ^ buf[plen << 1])); - */ - - /* - * Convert coordinates and check that the point is valid. - */ - zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t); - memcpy(Q.c[0], cc->R2, zlen); - memcpy(Q.c[1], cc->b, zlen); - set_one(Q.c[2], cc->p); - r &= ~run_code(P, &Q, cc, code_check); - return r; -} - -/* - * Encode a point. This method assumes that the point is correct and is - * not the point at infinity. Encoded size is always 1+2*plen, where - * plen is the field modulus length, in bytes. - */ -static void -point_encode(void *dst, const jacobian *P, const curve_params *cc) -{ - unsigned char *buf; - uint32_t xbl; - size_t plen; - jacobian Q, T; - - buf = dst; - xbl = cc->p[0]; - xbl -= (xbl >> 5); - plen = (xbl + 7) >> 3; - buf[0] = 0x04; - memcpy(&Q, P, sizeof *P); - set_one(T.c[2], cc->p); - run_code(&Q, &T, cc, code_affine); - br_i31_encode(buf + 1, plen, Q.c[0]); - br_i31_encode(buf + 1 + plen, plen, Q.c[1]); -} - -static const br_ec_curve_def * -id_to_curve_def(int curve) -{ - switch (curve) { - case BR_EC_secp256r1: - return &br_secp256r1; - case BR_EC_secp384r1: - return &br_secp384r1; - case BR_EC_secp521r1: - return &br_secp521r1; - } - return NULL; -} - -static const unsigned char * -api_generator(int curve, size_t *len) -{ - const br_ec_curve_def *cd; - - cd = id_to_curve_def(curve); - *len = cd->generator_len; - return cd->generator; -} - -static const unsigned char * -api_order(int curve, size_t *len) -{ - const br_ec_curve_def *cd; - - cd = id_to_curve_def(curve); - *len = cd->order_len; - return cd->order; -} - -static size_t -api_xoff(int curve, size_t *len) -{ - api_generator(curve, len); - *len >>= 1; - return 1; -} - -static uint32_t -api_mul(unsigned char *G, size_t Glen, - const unsigned char *x, size_t xlen, int curve) -{ - uint32_t r; - const curve_params *cc; - jacobian P; - - cc = id_to_curve(curve); - r = point_decode(&P, G, Glen, cc); - point_mul(&P, x, xlen, cc); - point_encode(G, &P, cc); - return r; -} - -static size_t -api_mulgen(unsigned char *R, - const unsigned char *x, size_t xlen, int curve) -{ - const unsigned char *G; - size_t Glen; - - G = api_generator(curve, &Glen); - memcpy(R, G, Glen); - api_mul(R, Glen, x, xlen, curve); - return Glen; -} - -static uint32_t -api_muladd(unsigned char *A, const unsigned char *B, size_t len, - const unsigned char *x, size_t xlen, - const unsigned char *y, size_t ylen, int curve) -{ - uint32_t r, t, z; - const curve_params *cc; - jacobian P, Q; - - /* - * TODO: see about merging the two ladders. Right now, we do - * two independent point multiplications, which is a bit - * wasteful of CPU resources (but yields short code). - */ - - cc = id_to_curve(curve); - r = point_decode(&P, A, len, cc); - if (B == NULL) { - size_t Glen; - - B = api_generator(curve, &Glen); - } - r &= point_decode(&Q, B, len, cc); - point_mul(&P, x, xlen, cc); - point_mul(&Q, y, ylen, cc); - - /* - * We want to compute P+Q. Since the base points A and B are distinct - * from infinity, and the multipliers are non-zero and lower than the - * curve order, then we know that P and Q are non-infinity. This - * leaves two special situations to test for: - * -- If P = Q then we must use point_double(). - * -- If P+Q = 0 then we must report an error. - */ - t = point_add(&P, &Q, cc); - point_double(&Q, cc); - z = br_i31_iszero(P.c[2]); - - /* - * If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we - * have the following: - * - * z = 0, t = 0 return P (normal addition) - * z = 0, t = 1 return P (normal addition) - * z = 1, t = 0 return Q (a 'double' case) - * z = 1, t = 1 report an error (P+Q = 0) - */ - CCOPY(z & ~t, &P, &Q, sizeof Q); - point_encode(A, &P, cc); - r &= ~(z & t); - - return r; -} - -/* see bearssl_ec.h */ -const br_ec_impl br_ec_prime_i31 = { - (uint32_t)0x03800000, - &api_generator, - &api_order, - &api_xoff, - &api_mul, - &api_mulgen, - &api_muladd -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_pubkey.c b/src/tls/bearssl/ec_pubkey.c deleted file mode 100644 index 2b886b381..000000000 --- a/src/tls/bearssl/ec_pubkey.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char POINT_LEN[] = { - 0, /* 0: not a valid curve ID */ - 43, /* sect163k1 */ - 43, /* sect163r1 */ - 43, /* sect163r2 */ - 51, /* sect193r1 */ - 51, /* sect193r2 */ - 61, /* sect233k1 */ - 61, /* sect233r1 */ - 61, /* sect239k1 */ - 73, /* sect283k1 */ - 73, /* sect283r1 */ - 105, /* sect409k1 */ - 105, /* sect409r1 */ - 145, /* sect571k1 */ - 145, /* sect571r1 */ - 41, /* secp160k1 */ - 41, /* secp160r1 */ - 41, /* secp160r2 */ - 49, /* secp192k1 */ - 49, /* secp192r1 */ - 57, /* secp224k1 */ - 57, /* secp224r1 */ - 65, /* secp256k1 */ - 65, /* secp256r1 */ - 97, /* secp384r1 */ - 133, /* secp521r1 */ - 65, /* brainpoolP256r1 */ - 97, /* brainpoolP384r1 */ - 129, /* brainpoolP512r1 */ - 32, /* curve25519 */ - 56, /* curve448 */ -}; - -/* see bearssl_ec.h */ -size_t -br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, - void *kbuf, const br_ec_private_key *sk) -{ - int curve; - size_t len; - - curve = sk->curve; - if (curve < 0 || curve >= 32 || curve >= (int)(sizeof POINT_LEN) - || ((impl->supported_curves >> curve) & 1) == 0) - { - return 0; - } - if (kbuf == NULL) { - return POINT_LEN[curve]; - } - len = impl->mulgen(kbuf, sk->x, sk->xlen, curve); - if (pk != NULL) { - pk->curve = curve; - pk->q = kbuf; - pk->qlen = len; - } - return len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_secp256r1.c b/src/tls/bearssl/ec_secp256r1.c deleted file mode 100644 index 39ba1c514..000000000 --- a/src/tls/bearssl/ec_secp256r1.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char P256_N[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, - 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 -}; - -static const unsigned char P256_G[] = { - 0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, - 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, - 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, - 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, - 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, - 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, - 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, - 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, - 0xF5 -}; - -/* see inner.h */ -const br_ec_curve_def br_secp256r1 = { - BR_EC_secp256r1, - P256_N, sizeof P256_N, - P256_G, sizeof P256_G -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_secp384r1.c b/src/tls/bearssl/ec_secp384r1.c deleted file mode 100644 index 27c0d2df7..000000000 --- a/src/tls/bearssl/ec_secp384r1.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char P384_N[] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, - 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, - 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 -}; - -static const unsigned char P384_G[] = { - 0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, - 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, - 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, - 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, - 0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, - 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, - 0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, - 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, - 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, - 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, - 0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, - 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, - 0x5F -}; - -/* see inner.h */ -const br_ec_curve_def br_secp384r1 = { - BR_EC_secp384r1, - P384_N, sizeof P384_N, - P384_G, sizeof P384_G -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ec_secp521r1.c b/src/tls/bearssl/ec_secp521r1.c deleted file mode 100644 index 34bb842cf..000000000 --- a/src/tls/bearssl/ec_secp521r1.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const unsigned char P521_N[] = { - 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, - 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, - 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, - 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, - 0x64, 0x09 -}; - -static const unsigned char P521_G[] = { - 0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, - 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, - 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, - 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, - 0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, - 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, - 0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, - 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, - 0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A, - 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F, - 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, - 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD, - 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72, - 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, - 0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70, - 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94, - 0x76, 0x9F, 0xD1, 0x66, 0x50 -}; - -/* see inner.h */ -const br_ec_curve_def br_secp521r1 = { - BR_EC_secp521r1, - P521_N, sizeof P521_N, - P521_G, sizeof P521_G -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_atr.c b/src/tls/bearssl/ecdsa_atr.c deleted file mode 100644 index cd0153a3a..000000000 --- a/src/tls/bearssl/ecdsa_atr.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -size_t -br_ecdsa_asn1_to_raw(void *sig, size_t sig_len) -{ - /* - * Note: this code is a bit lenient in that it accepts a few - * deviations to DER with regards to minimality of encoding of - * lengths and integer values. These deviations are still - * unambiguous. - * - * Signature format is a SEQUENCE of two INTEGER values. We - * support only integers of less than 127 bytes each (signed - * encoding) so the resulting raw signature will have length - * at most 254 bytes. - */ - - unsigned char *buf, *r, *s; - size_t zlen, rlen, slen, off; - unsigned char tmp[254]; - - buf = sig; - if (sig_len < 8) { - return 0; - } - - /* - * First byte is SEQUENCE tag. - */ - if (buf[0] != 0x30) { - return 0; - } - - /* - * The SEQUENCE length will be encoded over one or two bytes. We - * limit the total SEQUENCE contents to 255 bytes, because it - * makes things simpler; this is enough for subgroup orders up - * to 999 bits. - */ - zlen = buf[1]; - if (zlen > 0x80) { - if (zlen != 0x81) { - return 0; - } - zlen = buf[2]; - if (zlen != sig_len - 3) { - return 0; - } - off = 3; - } else { - if (zlen != sig_len - 2) { - return 0; - } - off = 2; - } - - /* - * First INTEGER (r). - */ - if (buf[off ++] != 0x02) { - return 0; - } - rlen = buf[off ++]; - if (rlen >= 0x80) { - return 0; - } - r = buf + off; - off += rlen; - - /* - * Second INTEGER (s). - */ - if (off + 2 > sig_len) { - return 0; - } - if (buf[off ++] != 0x02) { - return 0; - } - slen = buf[off ++]; - if (slen >= 0x80 || slen != sig_len - off) { - return 0; - } - s = buf + off; - - /* - * Removing leading zeros from r and s. - */ - while (rlen > 0 && *r == 0) { - rlen --; - r ++; - } - while (slen > 0 && *s == 0) { - slen --; - s ++; - } - - /* - * Compute common length for the two integers, then copy integers - * into the temporary buffer, and finally copy it back over the - * signature buffer. - */ - zlen = rlen > slen ? rlen : slen; - sig_len = zlen << 1; - memset(tmp, 0, sig_len); - memcpy(tmp + zlen - rlen, r, rlen); - memcpy(tmp + sig_len - slen, s, slen); - memcpy(sig, tmp, sig_len); - return sig_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_default_sign_asn1.c b/src/tls/bearssl/ecdsa_default_sign_asn1.c deleted file mode 100644 index 09fc7a6a9..000000000 --- a/src/tls/bearssl/ecdsa_default_sign_asn1.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -br_ecdsa_sign -br_ecdsa_sign_asn1_get_default(void) -{ -#if BR_LOMUL - return &br_ecdsa_i15_sign_asn1; -#else - return &br_ecdsa_i31_sign_asn1; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_default_sign_raw.c b/src/tls/bearssl/ecdsa_default_sign_raw.c deleted file mode 100644 index e1b243c8e..000000000 --- a/src/tls/bearssl/ecdsa_default_sign_raw.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -br_ecdsa_sign -br_ecdsa_sign_raw_get_default(void) -{ -#if BR_LOMUL - return &br_ecdsa_i15_sign_raw; -#else - return &br_ecdsa_i31_sign_raw; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_default_vrfy_asn1.c b/src/tls/bearssl/ecdsa_default_vrfy_asn1.c deleted file mode 100644 index f4ce11698..000000000 --- a/src/tls/bearssl/ecdsa_default_vrfy_asn1.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -br_ecdsa_vrfy -br_ecdsa_vrfy_asn1_get_default(void) -{ -#if BR_LOMUL - return &br_ecdsa_i15_vrfy_asn1; -#else - return &br_ecdsa_i31_vrfy_asn1; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_default_vrfy_raw.c b/src/tls/bearssl/ecdsa_default_vrfy_raw.c deleted file mode 100644 index db13f1b99..000000000 --- a/src/tls/bearssl/ecdsa_default_vrfy_raw.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ec.h */ -br_ecdsa_vrfy -br_ecdsa_vrfy_raw_get_default(void) -{ -#if BR_LOMUL - return &br_ecdsa_i15_vrfy_raw; -#else - return &br_ecdsa_i31_vrfy_raw; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i15_bits.c b/src/tls/bearssl/ecdsa_i15_bits.c deleted file mode 100644 index 21c939513..000000000 --- a/src/tls/bearssl/ecdsa_i15_bits.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_ecdsa_i15_bits2int(uint16_t *x, - const void *src, size_t len, uint32_t ebitlen) -{ - uint32_t bitlen, hbitlen; - int sc; - - bitlen = ebitlen - (ebitlen >> 4); - hbitlen = (uint32_t)len << 3; - if (hbitlen > bitlen) { - len = (bitlen + 7) >> 3; - sc = (int)((hbitlen - bitlen) & 7); - } else { - sc = 0; - } - br_i15_zero(x, ebitlen); - br_i15_decode(x, src, len); - br_i15_rshift(x, sc); - x[0] = ebitlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i15_sign_asn1.c b/src/tls/bearssl/ecdsa_i15_sign_asn1.c deleted file mode 100644 index ab6d30cca..000000000 --- a/src/tls/bearssl/ecdsa_i15_sign_asn1.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -size_t -br_ecdsa_i15_sign_asn1(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig) -{ - unsigned char rsig[(ORDER_LEN << 1) + 12]; - size_t sig_len; - - sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig); - if (sig_len == 0) { - return 0; - } - sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len); - memcpy(sig, rsig, sig_len); - return sig_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i15_sign_raw.c b/src/tls/bearssl/ecdsa_i15_sign_raw.c deleted file mode 100644 index f88628670..000000000 --- a/src/tls/bearssl/ecdsa_i15_sign_raw.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) -#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) -#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -size_t -br_ecdsa_i15_sign_raw(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig) -{ - /* - * IMPORTANT: this code is fit only for curves with a prime - * order. This is needed so that modular reduction of the X - * coordinate of a point can be done with a simple subtraction. - * We also rely on the last byte of the curve order to be distinct - * from 0 and 1. - */ - const br_ec_curve_def *cd; - uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN]; - uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN]; - unsigned char tt[ORDER_LEN << 1]; - unsigned char eU[POINT_LEN]; - size_t hash_len, nlen, ulen; - uint16_t n0i; - uint32_t ctl; - br_hmac_drbg_context drbg; - - /* - * If the curve is not supported, then exit with an error. - */ - if (((impl->supported_curves >> sk->curve) & 1) == 0) { - return 0; - } - - /* - * Get the curve parameters (generator and order). - */ - switch (sk->curve) { - case BR_EC_secp256r1: - cd = &br_secp256r1; - break; - case BR_EC_secp384r1: - cd = &br_secp384r1; - break; - case BR_EC_secp521r1: - cd = &br_secp521r1; - break; - default: - return 0; - } - - /* - * Get modulus. - */ - nlen = cd->order_len; - br_i15_decode(n, cd->order, nlen); - n0i = br_i15_ninv15(n[1]); - - /* - * Get private key as an i15 integer. This also checks that the - * private key is well-defined (not zero, and less than the - * curve order). - */ - if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) { - return 0; - } - if (br_i15_iszero(x)) { - return 0; - } - - /* - * Get hash length. - */ - hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; - - /* - * Truncate and reduce the hash value modulo the curve order. - */ - br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]); - br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1); - - /* - * RFC 6979 generation of the "k" value. - * - * The process uses HMAC_DRBG (with the hash function used to - * process the message that is to be signed). The seed is the - * concatenation of the encodings of the private key and - * the hash value (after truncation and modular reduction). - */ - br_i15_encode(tt, nlen, x); - br_i15_encode(tt + nlen, nlen, m); - br_hmac_drbg_init(&drbg, hf, tt, nlen << 1); - for (;;) { - br_hmac_drbg_generate(&drbg, tt, nlen); - br_ecdsa_i15_bits2int(k, tt, nlen, n[0]); - if (br_i15_iszero(k)) { - continue; - } - if (br_i15_sub(k, n, 0)) { - break; - } - } - - /* - * Compute k*G and extract the X coordinate, then reduce it - * modulo the curve order. Since we support only curves with - * prime order, that reduction is only a matter of computing - * a subtraction. - */ - br_i15_encode(tt, nlen, k); - ulen = impl->mulgen(eU, tt, nlen, sk->curve); - br_i15_zero(r, n[0]); - br_i15_decode(r, &eU[1], ulen >> 1); - r[0] = n[0]; - br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1); - - /* - * Compute 1/k in double-Montgomery representation. We do so by - * first converting _from_ Montgomery representation (twice), - * then using a modular exponentiation. - */ - br_i15_from_monty(k, n, n0i); - br_i15_from_monty(k, n, n0i); - memcpy(tt, cd->order, nlen); - tt[nlen - 1] -= 2; - br_i15_modpow(k, tt, nlen, n, n0i, t1, t2); - - /* - * Compute s = (m+xr)/k (mod n). - * The k[] array contains R^2/k (double-Montgomery representation); - * we thus can use direct Montgomery multiplications and conversions - * from Montgomery, avoiding any call to br_i15_to_monty() (which - * is slower). - */ - br_i15_from_monty(m, n, n0i); - br_i15_montymul(t1, x, r, n, n0i); - ctl = br_i15_add(t1, m, 1); - ctl |= br_i15_sub(t1, n, 0) ^ 1; - br_i15_sub(t1, n, ctl); - br_i15_montymul(s, t1, k, n, n0i); - - /* - * Encode r and s in the signature. - */ - br_i15_encode(sig, nlen, r); - br_i15_encode((unsigned char *)sig + nlen, nlen, s); - return nlen << 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i15_vrfy_asn1.c b/src/tls/bearssl/ecdsa_i15_vrfy_asn1.c deleted file mode 100644 index 5b93e436b..000000000 --- a/src/tls/bearssl/ecdsa_i15_vrfy_asn1.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -uint32_t -br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len) -{ - /* - * We use a double-sized buffer because a malformed ASN.1 signature - * may trigger a size expansion when converting to "raw" format. - */ - unsigned char rsig[(FIELD_LEN << 2) + 24]; - - if (sig_len > ((sizeof rsig) >> 1)) { - return 0; - } - memcpy(rsig, sig, sig_len); - sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); - return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i15_vrfy_raw.c b/src/tls/bearssl/ecdsa_i15_vrfy_raw.c deleted file mode 100644 index fc40b8645..000000000 --- a/src/tls/bearssl/ecdsa_i15_vrfy_raw.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15) -#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) - -/* see bearssl_ec.h */ -uint32_t -br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len) -{ - /* - * IMPORTANT: this code is fit only for curves with a prime - * order. This is needed so that modular reduction of the X - * coordinate of a point can be done with a simple subtraction. - */ - const br_ec_curve_def *cd; - uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN]; - unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3]; - unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3]; - unsigned char eU[POINT_LEN]; - size_t nlen, rlen, ulen; - uint16_t n0i; - uint32_t res; - - /* - * If the curve is not supported, then report an error. - */ - if (((impl->supported_curves >> pk->curve) & 1) == 0) { - return 0; - } - - /* - * Get the curve parameters (generator and order). - */ - switch (pk->curve) { - case BR_EC_secp256r1: - cd = &br_secp256r1; - break; - case BR_EC_secp384r1: - cd = &br_secp384r1; - break; - case BR_EC_secp521r1: - cd = &br_secp521r1; - break; - default: - return 0; - } - - /* - * Signature length must be even. - */ - if (sig_len & 1) { - return 0; - } - rlen = sig_len >> 1; - - /* - * Public key point must have the proper size for this curve. - */ - if (pk->qlen != cd->generator_len) { - return 0; - } - - /* - * Get modulus; then decode the r and s values. They must be - * lower than the modulus, and s must not be null. - */ - nlen = cd->order_len; - br_i15_decode(n, cd->order, nlen); - n0i = br_i15_ninv15(n[1]); - if (!br_i15_decode_mod(r, sig, rlen, n)) { - return 0; - } - if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) { - return 0; - } - if (br_i15_iszero(s)) { - return 0; - } - - /* - * Invert s. We do that with a modular exponentiation; we use - * the fact that for all the curves we support, the least - * significant byte is not 0 or 1, so we can subtract 2 without - * any carry to process. - * We also want 1/s in Montgomery representation, which can be - * done by converting _from_ Montgomery representation before - * the inversion (because (1/s)*R = 1/(s/R)). - */ - br_i15_from_monty(s, n, n0i); - memcpy(tx, cd->order, nlen); - tx[nlen - 1] -= 2; - br_i15_modpow(s, tx, nlen, n, n0i, t1, t2); - - /* - * Truncate the hash to the modulus length (in bits) and reduce - * it modulo the curve order. The modular reduction can be done - * with a subtraction since the truncation already reduced the - * value to the modulus bit length. - */ - br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]); - br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1); - - /* - * Multiply the (truncated, reduced) hash value with 1/s, result in - * t2, encoded in ty. - */ - br_i15_montymul(t2, t1, s, n, n0i); - br_i15_encode(ty, nlen, t2); - - /* - * Multiply r with 1/s, result in t1, encoded in tx. - */ - br_i15_montymul(t1, r, s, n, n0i); - br_i15_encode(tx, nlen, t1); - - /* - * Compute the point x*Q + y*G. - */ - ulen = cd->generator_len; - memcpy(eU, pk->q, ulen); - res = impl->muladd(eU, NULL, ulen, - tx, nlen, ty, nlen, cd->curve); - - /* - * Get the X coordinate, reduce modulo the curve order, and - * compare with the 'r' value. - * - * The modular reduction can be done with subtractions because - * we work with curves of prime order, so the curve order is - * close to the field order (Hasse's theorem). - */ - br_i15_zero(t1, n[0]); - br_i15_decode(t1, &eU[1], ulen >> 1); - t1[0] = n[0]; - br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1); - res &= ~br_i15_sub(t1, r, 1); - res &= br_i15_iszero(t1); - return res; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i31_bits.c b/src/tls/bearssl/ecdsa_i31_bits.c deleted file mode 100644 index 97ab7facd..000000000 --- a/src/tls/bearssl/ecdsa_i31_bits.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_ecdsa_i31_bits2int(uint32_t *x, - const void *src, size_t len, uint32_t ebitlen) -{ - uint32_t bitlen, hbitlen; - int sc; - - bitlen = ebitlen - (ebitlen >> 5); - hbitlen = (uint32_t)len << 3; - if (hbitlen > bitlen) { - len = (bitlen + 7) >> 3; - sc = (int)((hbitlen - bitlen) & 7); - } else { - sc = 0; - } - br_i31_zero(x, ebitlen); - br_i31_decode(x, src, len); - br_i31_rshift(x, sc); - x[0] = ebitlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i31_sign_asn1.c b/src/tls/bearssl/ecdsa_i31_sign_asn1.c deleted file mode 100644 index 6131bb328..000000000 --- a/src/tls/bearssl/ecdsa_i31_sign_asn1.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -size_t -br_ecdsa_i31_sign_asn1(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig) -{ - unsigned char rsig[(ORDER_LEN << 1) + 12]; - size_t sig_len; - - sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig); - if (sig_len == 0) { - return 0; - } - sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len); - memcpy(sig, rsig, sig_len); - return sig_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i31_sign_raw.c b/src/tls/bearssl/ecdsa_i31_sign_raw.c deleted file mode 100644 index 6a1d8a2f5..000000000 --- a/src/tls/bearssl/ecdsa_i31_sign_raw.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) -#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) -#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -size_t -br_ecdsa_i31_sign_raw(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig) -{ - /* - * IMPORTANT: this code is fit only for curves with a prime - * order. This is needed so that modular reduction of the X - * coordinate of a point can be done with a simple subtraction. - * We also rely on the last byte of the curve order to be distinct - * from 0 and 1. - */ - const br_ec_curve_def *cd; - uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN]; - uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN]; - unsigned char tt[ORDER_LEN << 1]; - unsigned char eU[POINT_LEN]; - size_t hash_len, nlen, ulen; - uint32_t n0i, ctl; - br_hmac_drbg_context drbg; - - /* - * If the curve is not supported, then exit with an error. - */ - if (((impl->supported_curves >> sk->curve) & 1) == 0) { - return 0; - } - - /* - * Get the curve parameters (generator and order). - */ - switch (sk->curve) { - case BR_EC_secp256r1: - cd = &br_secp256r1; - break; - case BR_EC_secp384r1: - cd = &br_secp384r1; - break; - case BR_EC_secp521r1: - cd = &br_secp521r1; - break; - default: - return 0; - } - - /* - * Get modulus. - */ - nlen = cd->order_len; - br_i31_decode(n, cd->order, nlen); - n0i = br_i31_ninv31(n[1]); - - /* - * Get private key as an i31 integer. This also checks that the - * private key is well-defined (not zero, and less than the - * curve order). - */ - if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) { - return 0; - } - if (br_i31_iszero(x)) { - return 0; - } - - /* - * Get hash length. - */ - hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; - - /* - * Truncate and reduce the hash value modulo the curve order. - */ - br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]); - br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1); - - /* - * RFC 6979 generation of the "k" value. - * - * The process uses HMAC_DRBG (with the hash function used to - * process the message that is to be signed). The seed is the - * concatenation of the encodings of the private key and - * the hash value (after truncation and modular reduction). - */ - br_i31_encode(tt, nlen, x); - br_i31_encode(tt + nlen, nlen, m); - br_hmac_drbg_init(&drbg, hf, tt, nlen << 1); - for (;;) { - br_hmac_drbg_generate(&drbg, tt, nlen); - br_ecdsa_i31_bits2int(k, tt, nlen, n[0]); - if (br_i31_iszero(k)) { - continue; - } - if (br_i31_sub(k, n, 0)) { - break; - } - } - - /* - * Compute k*G and extract the X coordinate, then reduce it - * modulo the curve order. Since we support only curves with - * prime order, that reduction is only a matter of computing - * a subtraction. - */ - br_i31_encode(tt, nlen, k); - ulen = impl->mulgen(eU, tt, nlen, sk->curve); - br_i31_zero(r, n[0]); - br_i31_decode(r, &eU[1], ulen >> 1); - r[0] = n[0]; - br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1); - - /* - * Compute 1/k in double-Montgomery representation. We do so by - * first converting _from_ Montgomery representation (twice), - * then using a modular exponentiation. - */ - br_i31_from_monty(k, n, n0i); - br_i31_from_monty(k, n, n0i); - memcpy(tt, cd->order, nlen); - tt[nlen - 1] -= 2; - br_i31_modpow(k, tt, nlen, n, n0i, t1, t2); - - /* - * Compute s = (m+xr)/k (mod n). - * The k[] array contains R^2/k (double-Montgomery representation); - * we thus can use direct Montgomery multiplications and conversions - * from Montgomery, avoiding any call to br_i31_to_monty() (which - * is slower). - */ - br_i31_from_monty(m, n, n0i); - br_i31_montymul(t1, x, r, n, n0i); - ctl = br_i31_add(t1, m, 1); - ctl |= br_i31_sub(t1, n, 0) ^ 1; - br_i31_sub(t1, n, ctl); - br_i31_montymul(s, t1, k, n, n0i); - - /* - * Encode r and s in the signature. - */ - br_i31_encode(sig, nlen, r); - br_i31_encode((unsigned char *)sig + nlen, nlen, s); - return nlen << 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i31_vrfy_asn1.c b/src/tls/bearssl/ecdsa_i31_vrfy_asn1.c deleted file mode 100644 index 91f1b68cd..000000000 --- a/src/tls/bearssl/ecdsa_i31_vrfy_asn1.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -/* see bearssl_ec.h */ -uint32_t -br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len) -{ - /* - * We use a double-sized buffer because a malformed ASN.1 signature - * may trigger a size expansion when converting to "raw" format. - */ - unsigned char rsig[(FIELD_LEN << 2) + 24]; - - if (sig_len > ((sizeof rsig) >> 1)) { - return 0; - } - memcpy(rsig, sig, sig_len); - sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); - return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_i31_vrfy_raw.c b/src/tls/bearssl/ecdsa_i31_vrfy_raw.c deleted file mode 100644 index d6e09f471..000000000 --- a/src/tls/bearssl/ecdsa_i31_vrfy_raw.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31) -#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1)) - -/* see bearssl_ec.h */ -uint32_t -br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len) -{ - /* - * IMPORTANT: this code is fit only for curves with a prime - * order. This is needed so that modular reduction of the X - * coordinate of a point can be done with a simple subtraction. - */ - const br_ec_curve_def *cd; - uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN]; - unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3]; - unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3]; - unsigned char eU[POINT_LEN]; - size_t nlen, rlen, ulen; - uint32_t n0i, res; - - /* - * If the curve is not supported, then report an error. - */ - if (((impl->supported_curves >> pk->curve) & 1) == 0) { - return 0; - } - - /* - * Get the curve parameters (generator and order). - */ - switch (pk->curve) { - case BR_EC_secp256r1: - cd = &br_secp256r1; - break; - case BR_EC_secp384r1: - cd = &br_secp384r1; - break; - case BR_EC_secp521r1: - cd = &br_secp521r1; - break; - default: - return 0; - } - - /* - * Signature length must be even. - */ - if (sig_len & 1) { - return 0; - } - rlen = sig_len >> 1; - - /* - * Public key point must have the proper size for this curve. - */ - if (pk->qlen != cd->generator_len) { - return 0; - } - - /* - * Get modulus; then decode the r and s values. They must be - * lower than the modulus, and s must not be null. - */ - nlen = cd->order_len; - br_i31_decode(n, cd->order, nlen); - n0i = br_i31_ninv31(n[1]); - if (!br_i31_decode_mod(r, sig, rlen, n)) { - return 0; - } - if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) { - return 0; - } - if (br_i31_iszero(s)) { - return 0; - } - - /* - * Invert s. We do that with a modular exponentiation; we use - * the fact that for all the curves we support, the least - * significant byte is not 0 or 1, so we can subtract 2 without - * any carry to process. - * We also want 1/s in Montgomery representation, which can be - * done by converting _from_ Montgomery representation before - * the inversion (because (1/s)*R = 1/(s/R)). - */ - br_i31_from_monty(s, n, n0i); - memcpy(tx, cd->order, nlen); - tx[nlen - 1] -= 2; - br_i31_modpow(s, tx, nlen, n, n0i, t1, t2); - - /* - * Truncate the hash to the modulus length (in bits) and reduce - * it modulo the curve order. The modular reduction can be done - * with a subtraction since the truncation already reduced the - * value to the modulus bit length. - */ - br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]); - br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1); - - /* - * Multiply the (truncated, reduced) hash value with 1/s, result in - * t2, encoded in ty. - */ - br_i31_montymul(t2, t1, s, n, n0i); - br_i31_encode(ty, nlen, t2); - - /* - * Multiply r with 1/s, result in t1, encoded in tx. - */ - br_i31_montymul(t1, r, s, n, n0i); - br_i31_encode(tx, nlen, t1); - - /* - * Compute the point x*Q + y*G. - */ - ulen = cd->generator_len; - memcpy(eU, pk->q, ulen); - res = impl->muladd(eU, NULL, ulen, - tx, nlen, ty, nlen, cd->curve); - - /* - * Get the X coordinate, reduce modulo the curve order, and - * compare with the 'r' value. - * - * The modular reduction can be done with subtractions because - * we work with curves of prime order, so the curve order is - * close to the field order (Hasse's theorem). - */ - br_i31_zero(t1, n[0]); - br_i31_decode(t1, &eU[1], ulen >> 1); - t1[0] = n[0]; - br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1); - res &= ~br_i31_sub(t1, r, 1); - res &= br_i31_iszero(t1); - return res; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ecdsa_rta.c b/src/tls/bearssl/ecdsa_rta.c deleted file mode 100644 index 921828fe6..000000000 --- a/src/tls/bearssl/ecdsa_rta.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Compute ASN.1 encoded length for the provided integer. The ASN.1 - * encoding is signed, so its leading bit must have value 0; it must - * also be of minimal length (so leading bytes of value 0 must be - * removed, except if that would contradict the rule about the sign - * bit). - */ -static size_t -asn1_int_length(const unsigned char *x, size_t xlen) -{ - while (xlen > 0 && *x == 0) { - x ++; - xlen --; - } - if (xlen == 0 || *x >= 0x80) { - xlen ++; - } - return xlen; -} - -/* see bearssl_ec.h */ -size_t -br_ecdsa_raw_to_asn1(void *sig, size_t sig_len) -{ - /* - * Internal buffer is large enough to accommodate a signature - * such that r and s fit on 125 bytes each (signed encoding), - * meaning a curve order of up to 999 bits. This is the limit - * that ensures "simple" length encodings. - */ - unsigned char *buf; - size_t hlen, rlen, slen, zlen, off; - unsigned char tmp[257]; - - buf = sig; - if ((sig_len & 1) != 0) { - return 0; - } - - /* - * Compute lengths for the two integers. - */ - hlen = sig_len >> 1; - rlen = asn1_int_length(buf, hlen); - slen = asn1_int_length(buf + hlen, hlen); - if (rlen > 125 || slen > 125) { - return 0; - } - - /* - * SEQUENCE header. - */ - tmp[0] = 0x30; - zlen = rlen + slen + 4; - if (zlen >= 0x80) { - tmp[1] = 0x81; - tmp[2] = zlen; - off = 3; - } else { - tmp[1] = zlen; - off = 2; - } - - /* - * First INTEGER (r). - */ - tmp[off ++] = 0x02; - tmp[off ++] = rlen; - if (rlen > hlen) { - tmp[off] = 0x00; - memcpy(tmp + off + 1, buf, hlen); - } else { - memcpy(tmp + off, buf + hlen - rlen, rlen); - } - off += rlen; - - /* - * Second INTEGER (s). - */ - tmp[off ++] = 0x02; - tmp[off ++] = slen; - if (slen > hlen) { - tmp[off] = 0x00; - memcpy(tmp + off + 1, buf + hlen, hlen); - } else { - memcpy(tmp + off, buf + sig_len - slen, slen); - } - off += slen; - - /* - * Return ASN.1 signature. - */ - memcpy(sig, tmp, off); - return off; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc16be.c b/src/tls/bearssl/enc16be.c deleted file mode 100644 index 06e4cf35e..000000000 --- a/src/tls/bearssl/enc16be.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc16be(void *dst, const uint16_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc16be(buf, *v ++); - buf += 2; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc16le.c b/src/tls/bearssl/enc16le.c deleted file mode 100644 index dcea1802b..000000000 --- a/src/tls/bearssl/enc16le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc16le(void *dst, const uint16_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc16le(buf, *v ++); - buf += 2; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc32be.c b/src/tls/bearssl/enc32be.c deleted file mode 100644 index 26fa3cee1..000000000 --- a/src/tls/bearssl/enc32be.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ - defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ - defined(ARDUINO_UNOR4_WIFI) - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc32be(void *dst, const uint32_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc32be(buf, *v ++); - buf += 4; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc32le.c b/src/tls/bearssl/enc32le.c deleted file mode 100644 index 740434df1..000000000 --- a/src/tls/bearssl/enc32le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc32le(void *dst, const uint32_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc32le(buf, *v ++); - buf += 4; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc64be.c b/src/tls/bearssl/enc64be.c deleted file mode 100644 index 0dea84c8a..000000000 --- a/src/tls/bearssl/enc64be.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc64be(void *dst, const uint64_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc64be(buf, *v ++); - buf += 8; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/enc64le.c b/src/tls/bearssl/enc64le.c deleted file mode 100644 index 992da2ba4..000000000 --- a/src/tls/bearssl/enc64le.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_range_enc64le(void *dst, const uint64_t *v, size_t num) -{ - unsigned char *buf; - - buf = dst; - while (num -- > 0) { - br_enc64le(buf, *v ++); - buf += 8; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/encode_ec_pk8der.c b/src/tls/bearssl/encode_ec_pk8der.c deleted file mode 100644 index 410c8b9b5..000000000 --- a/src/tls/bearssl/encode_ec_pk8der.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_x509.h */ -size_t -br_encode_ec_pkcs8_der(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk) -{ - /* - * ASN.1 format: - * - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] PublicKey OPTIONAL ]], - * ... - * } - * - * We don't include attributes or public key (the public key - * is included in the private key value instead). The - * 'version' field is an INTEGER that we will set to 0 - * (meaning 'v1', compatible with previous versions of PKCS#8). - * The 'privateKeyAlgorithm' structure is an AlgorithmIdentifier - * whose OID should be id-ecPublicKey, with, as parameters, the - * curve OID. The 'privateKey' is an OCTET STRING, whose value - * is the "raw DER" encoding of the key pair. - */ - - /* - * OID id-ecPublicKey (1.2.840.10045.2.1), DER-encoded (with - * the tag). - */ - static const unsigned char OID_ECPUBKEY[] = { - 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 - }; - - size_t len_version, len_privateKeyAlgorithm, len_privateKeyValue; - size_t len_privateKey, len_seq; - const unsigned char *oid; - - oid = br_get_curve_OID(sk->curve); - if (oid == NULL) { - return 0; - } - len_version = 3; - len_privateKeyAlgorithm = 2 + sizeof OID_ECPUBKEY + 2 + oid[0]; - len_privateKeyValue = br_encode_ec_raw_der_inner(NULL, sk, pk, 0); - len_privateKey = 1 + len_of_len(len_privateKeyValue) - + len_privateKeyValue; - len_seq = len_version + len_privateKeyAlgorithm + len_privateKey; - - if (dest == NULL) { - return 1 + len_of_len(len_seq) + len_seq; - } else { - unsigned char *buf; - size_t lenlen; - - buf = dest; - *buf ++ = 0x30; /* SEQUENCE tag */ - lenlen = br_asn1_encode_length(buf, len_seq); - buf += lenlen; - - /* version */ - *buf ++ = 0x02; - *buf ++ = 0x01; - *buf ++ = 0x00; - - /* privateKeyAlgorithm */ - *buf ++ = 0x30; - *buf ++ = (sizeof OID_ECPUBKEY) + 2 + oid[0]; - memcpy(buf, OID_ECPUBKEY, sizeof OID_ECPUBKEY); - buf += sizeof OID_ECPUBKEY; - *buf ++ = 0x06; - memcpy(buf, oid, 1 + oid[0]); - buf += 1 + oid[0]; - - /* privateKey */ - *buf ++ = 0x04; - buf += br_asn1_encode_length(buf, len_privateKeyValue); - br_encode_ec_raw_der_inner(buf, sk, pk, 0); - - return 1 + lenlen + len_seq; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/encode_ec_rawder.c b/src/tls/bearssl/encode_ec_rawder.c deleted file mode 100644 index 305411dc0..000000000 --- a/src/tls/bearssl/encode_ec_rawder.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -const unsigned char * -br_get_curve_OID(int curve) -{ - static const unsigned char OID_secp256r1[] = { - 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 - }; - static const unsigned char OID_secp384r1[] = { - 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22 - }; - static const unsigned char OID_secp521r1[] = { - 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23 - }; - - switch (curve) { - case BR_EC_secp256r1: return OID_secp256r1; - case BR_EC_secp384r1: return OID_secp384r1; - case BR_EC_secp521r1: return OID_secp521r1; - default: - return NULL; - } -} - -/* see inner.h */ -size_t -br_encode_ec_raw_der_inner(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk, - int include_curve_oid) -{ - /* - * ASN.1 format: - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - * - * The tages '[0]' and '[1]' are explicit. The 'ECParameters' - * is a CHOICE; in our case, it will always be an OBJECT IDENTIFIER - * that identifies the curve. - * - * The value of the 'privateKey' field is the raw unsigned big-endian - * encoding of the private key (integer modulo the curve subgroup - * order); there is no INTEGER tag, and the leading bit may be 1. - * Also, leading bytes of value 0x00 are _not_ removed. - * - * The 'publicKey' contents are the raw encoded public key point, - * normally uncompressed (leading byte of value 0x04, followed - * by the unsigned big-endian encodings of the X and Y coordinates, - * padded to the full field length if necessary). - */ - - size_t len_version, len_privateKey, len_parameters, len_publicKey; - size_t len_publicKey_bits, len_seq; - const unsigned char *oid; - - if (include_curve_oid) { - oid = br_get_curve_OID(sk->curve); - if (oid == NULL) { - return 0; - } - } else { - oid = NULL; - } - len_version = 3; - len_privateKey = 1 + len_of_len(sk->xlen) + sk->xlen; - if (include_curve_oid) { - len_parameters = 4 + oid[0]; - } else { - len_parameters = 0; - } - if (pk == NULL) { - len_publicKey = 0; - len_publicKey_bits = 0; - } else { - len_publicKey_bits = 2 + len_of_len(pk->qlen) + pk->qlen; - len_publicKey = 1 + len_of_len(len_publicKey_bits) - + len_publicKey_bits; - } - len_seq = len_version + len_privateKey + len_parameters + len_publicKey; - if (dest == NULL) { - return 1 + len_of_len(len_seq) + len_seq; - } else { - unsigned char *buf; - size_t lenlen; - - buf = dest; - *buf ++ = 0x30; /* SEQUENCE tag */ - lenlen = br_asn1_encode_length(buf, len_seq); - buf += lenlen; - - /* version */ - *buf ++ = 0x02; - *buf ++ = 0x01; - *buf ++ = 0x01; - - /* privateKey */ - *buf ++ = 0x04; - buf += br_asn1_encode_length(buf, sk->xlen); - memcpy(buf, sk->x, sk->xlen); - buf += sk->xlen; - - /* parameters */ - if (include_curve_oid) { - *buf ++ = 0xA0; - *buf ++ = oid[0] + 2; - *buf ++ = 0x06; - memcpy(buf, oid, oid[0] + 1); - buf += oid[0] + 1; - } - - /* publicKey */ - if (pk != NULL) { - *buf ++ = 0xA1; - buf += br_asn1_encode_length(buf, len_publicKey_bits); - *buf ++ = 0x03; - buf += br_asn1_encode_length(buf, pk->qlen + 1); - *buf ++ = 0x00; - memcpy(buf, pk->q, pk->qlen); - /* buf += pk->qlen; */ - } - - return 1 + lenlen + len_seq; - } -} - -/* see bearssl_x509.h */ -size_t -br_encode_ec_raw_der(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk) -{ - return br_encode_ec_raw_der_inner(dest, sk, pk, 1); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/encode_rsa_pk8der.c b/src/tls/bearssl/encode_rsa_pk8der.c deleted file mode 100644 index a8f9ef78c..000000000 --- a/src/tls/bearssl/encode_rsa_pk8der.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_x509.h */ -size_t -br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, - const br_rsa_public_key *pk, const void *d, size_t dlen) -{ - /* - * ASN.1 format: - * - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] PublicKey OPTIONAL ]], - * ... - * } - * - * We don't include attributes or public key. The 'version' field - * is an INTEGER that we will set to 0 (meaning 'v1', compatible - * with previous versions of PKCS#8). The 'privateKeyAlgorithm' - * structure is an AlgorithmIdentifier whose OID should be - * rsaEncryption, with NULL parameters. The 'privateKey' is an - * OCTET STRING, whose value is the "raw DER" encoding of the - * key pair. - * - * Since the private key value comes last, this function really - * adds a header, which is mostly fixed (only some lengths have - * to be modified. - */ - - /* - * Concatenation of: - * - DER encoding of an INTEGER of value 0 (the 'version' field) - * - DER encoding of a PrivateKeyAlgorithmIdentifier that uses - * the rsaEncryption OID, and NULL parameters - * - An OCTET STRING tag - */ - static const unsigned char PK8_HEAD[] = { - 0x02, 0x01, 0x00, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, - 0x04 - }; - - size_t len_raw, len_seq; - - len_raw = br_encode_rsa_raw_der(NULL, sk, pk, d, dlen); - len_seq = (sizeof PK8_HEAD) + len_of_len(len_raw) + len_raw; - if (dest == NULL) { - return 1 + len_of_len(len_seq) + len_seq; - } else { - unsigned char *buf; - size_t lenlen; - - buf = dest; - *buf ++ = 0x30; /* SEQUENCE tag */ - lenlen = br_asn1_encode_length(buf, len_seq); - buf += lenlen; - - /* version, privateKeyAlgorithm, privateKey tag */ - memcpy(buf, PK8_HEAD, sizeof PK8_HEAD); - buf += sizeof PK8_HEAD; - - /* privateKey */ - buf += br_asn1_encode_length(buf, len_raw); - br_encode_rsa_raw_der(buf, sk, pk, d, dlen); - - return 1 + lenlen + len_seq; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/encode_rsa_rawder.c b/src/tls/bearssl/encode_rsa_rawder.c deleted file mode 100644 index 5e63f4db4..000000000 --- a/src/tls/bearssl/encode_rsa_rawder.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_x509.h */ -size_t -br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, - const br_rsa_public_key *pk, const void *d, size_t dlen) -{ - /* - * ASN.1 format: - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - * - * The 'version' field is an INTEGER of value 0 (meaning: there - * are exactly two prime factors), and 'otherPrimeInfos' will - * be absent (because there are exactly two prime factors). - */ - - br_asn1_uint num[9]; - size_t u, slen; - - /* - * For all INTEGER values, get the pointer and length for the - * data bytes. - */ - num[0] = br_asn1_uint_prepare(NULL, 0); - num[1] = br_asn1_uint_prepare(pk->n, pk->nlen); - num[2] = br_asn1_uint_prepare(pk->e, pk->elen); - num[3] = br_asn1_uint_prepare(d, dlen); - num[4] = br_asn1_uint_prepare(sk->p, sk->plen); - num[5] = br_asn1_uint_prepare(sk->q, sk->qlen); - num[6] = br_asn1_uint_prepare(sk->dp, sk->dplen); - num[7] = br_asn1_uint_prepare(sk->dq, sk->dqlen); - num[8] = br_asn1_uint_prepare(sk->iq, sk->iqlen); - - /* - * Get the length of the SEQUENCE contents. - */ - slen = 0; - for (u = 0; u < 9; u ++) { - uint32_t ilen; - - ilen = num[u].asn1len; - slen += 1 + len_of_len(ilen) + ilen; - } - - if (dest == NULL) { - return 1 + len_of_len(slen) + slen; - } else { - unsigned char *buf; - size_t lenlen; - - buf = dest; - *buf ++ = 0x30; /* SEQUENCE tag */ - lenlen = br_asn1_encode_length(buf, slen); - buf += lenlen; - for (u = 0; u < 9; u ++) { - buf += br_asn1_encode_uint(buf, num[u]); - } - return 1 + lenlen + slen; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/gcm.c b/src/tls/bearssl/gcm.c deleted file mode 100644 index 7bbfaeab8..000000000 --- a/src/tls/bearssl/gcm.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Implementation Notes - * ==================== - * - * Since CTR and GHASH implementations can handle only full blocks, a - * 16-byte buffer (buf[]) is maintained in the context: - * - * - When processing AAD, buf[] contains the 0-15 unprocessed bytes. - * - * - When doing CTR encryption / decryption, buf[] contains the AES output - * for the last partial block, to be used with the next few bytes of - * data, as well as the already encrypted bytes. For instance, if the - * processed data length so far is 21 bytes, then buf[0..4] contains - * the five last encrypted bytes, and buf[5..15] contains the next 11 - * AES output bytes to be XORed with the next 11 bytes of input. - * - * The recorded AES output bytes are used to complete the block when - * the corresponding bytes are obtained. Note that buf[] always - * contains the _encrypted_ bytes, whether we apply encryption or - * decryption: these bytes are used as input to GHASH when the block - * is complete. - * - * In both cases, the low bits of the data length counters (count_aad, - * count_ctr) are used to work out the current situation. - */ - -/* see bearssl_aead.h */ -void -br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh) -{ - unsigned char iv[12]; - - ctx->vtable = &br_gcm_vtable; - ctx->bctx = bctx; - ctx->gh = gh; - - /* - * The GHASH key h[] is the raw encryption of the all-zero - * block. Since we only have a CTR implementation, we use it - * with an all-zero IV and a zero counter, to CTR-encrypt an - * all-zero block. - */ - memset(ctx->h, 0, sizeof ctx->h); - memset(iv, 0, sizeof iv); - (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h); -} - -/* see bearssl_aead.h */ -void -br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len) -{ - /* - * If the provided nonce is 12 bytes, then this is the initial - * IV for CTR mode; it will be used with a counter that starts - * at 2 (value 1 is for encrypting the GHASH output into the tag). - * - * If the provided nonce has any other length, then it is hashed - * (with GHASH) into a 16-byte value that will be the IV for CTR - * (both 12-byte IV and 32-bit counter). - */ - if (len == 12) { - memcpy(ctx->j0_1, iv, 12); - ctx->j0_2 = 1; - } else { - unsigned char ty[16], tmp[16]; - - memset(ty, 0, sizeof ty); - ctx->gh(ty, ctx->h, iv, len); - memset(tmp, 0, 8); - br_enc64be(tmp + 8, (uint64_t)len << 3); - ctx->gh(ty, ctx->h, tmp, 16); - memcpy(ctx->j0_1, ty, 12); - ctx->j0_2 = br_dec32be(ty + 12); - } - ctx->jc = ctx->j0_2 + 1; - memset(ctx->y, 0, sizeof ctx->y); - ctx->count_aad = 0; - ctx->count_ctr = 0; -} - -/* see bearssl_aead.h */ -void -br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len) -{ - size_t ptr, dlen; - - ptr = (size_t)ctx->count_aad & (size_t)15; - if (ptr != 0) { - /* - * If there is a partial block, then we first try to - * complete it. - */ - size_t clen; - - clen = 16 - ptr; - if (len < clen) { - memcpy(ctx->buf + ptr, data, len); - ctx->count_aad += (uint64_t)len; - return; - } - memcpy(ctx->buf + ptr, data, clen); - ctx->gh(ctx->y, ctx->h, ctx->buf, 16); - data = (const unsigned char *)data + clen; - len -= clen; - ctx->count_aad += (uint64_t)clen; - } - - /* - * Now AAD is aligned on a 16-byte block (with regards to GHASH). - * We process all complete blocks, and save the last partial - * block. - */ - dlen = len & ~(size_t)15; - ctx->gh(ctx->y, ctx->h, data, dlen); - memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen); - ctx->count_aad += (uint64_t)len; -} - -/* see bearssl_aead.h */ -void -br_gcm_flip(br_gcm_context *ctx) -{ - /* - * We complete the GHASH computation if there is a partial block. - * The GHASH implementation automatically applies padding with - * zeros. - */ - size_t ptr; - - ptr = (size_t)ctx->count_aad & (size_t)15; - if (ptr != 0) { - ctx->gh(ctx->y, ctx->h, ctx->buf, ptr); - } -} - -/* see bearssl_aead.h */ -void -br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len) -{ - unsigned char *buf; - size_t ptr, dlen; - - buf = data; - ptr = (size_t)ctx->count_ctr & (size_t)15; - if (ptr != 0) { - /* - * If we have a partial block, then we try to complete it. - */ - size_t u, clen; - - clen = 16 - ptr; - if (len < clen) { - clen = len; - } - for (u = 0; u < clen; u ++) { - unsigned x, y; - - x = buf[u]; - y = x ^ ctx->buf[ptr + u]; - ctx->buf[ptr + u] = encrypt ? y : x; - buf[u] = y; - } - ctx->count_ctr += (uint64_t)clen; - buf += clen; - len -= clen; - if (ptr + clen < 16) { - return; - } - ctx->gh(ctx->y, ctx->h, ctx->buf, 16); - } - - /* - * Process full blocks. - */ - dlen = len & ~(size_t)15; - if (!encrypt) { - ctx->gh(ctx->y, ctx->h, buf, dlen); - } - ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen); - if (encrypt) { - ctx->gh(ctx->y, ctx->h, buf, dlen); - } - buf += dlen; - len -= dlen; - ctx->count_ctr += (uint64_t)dlen; - - if (len > 0) { - /* - * There is a partial block. - */ - size_t u; - - memset(ctx->buf, 0, sizeof ctx->buf); - ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, - ctx->jc, ctx->buf, 16); - for (u = 0; u < len; u ++) { - unsigned x, y; - - x = buf[u]; - y = x ^ ctx->buf[u]; - ctx->buf[u] = encrypt ? y : x; - buf[u] = y; - } - ctx->count_ctr += (uint64_t)len; - } -} - -/* see bearssl_aead.h */ -void -br_gcm_get_tag(br_gcm_context *ctx, void *tag) -{ - size_t ptr; - unsigned char tmp[16]; - - ptr = (size_t)ctx->count_ctr & (size_t)15; - if (ptr > 0) { - /* - * There is a partial block: encrypted/decrypted data has - * been produced, but the encrypted bytes must still be - * processed by GHASH. - */ - ctx->gh(ctx->y, ctx->h, ctx->buf, ptr); - } - - /* - * Final block for GHASH: the AAD and plaintext lengths (in bits). - */ - br_enc64be(tmp, ctx->count_aad << 3); - br_enc64be(tmp + 8, ctx->count_ctr << 3); - ctx->gh(ctx->y, ctx->h, tmp, 16); - - /* - * Tag is the GHASH output XORed with the encryption of the - * nonce with the initial counter value. - */ - memcpy(tag, ctx->y, 16); - (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16); -} - -/* see bearssl_aead.h */ -void -br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len) -{ - unsigned char tmp[16]; - - br_gcm_get_tag(ctx, tmp); - memcpy(tag, tmp, len); -} - -/* see bearssl_aead.h */ -uint32_t -br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len) -{ - unsigned char tmp[16]; - size_t u; - int x; - - br_gcm_get_tag(ctx, tmp); - x = 0; - for (u = 0; u < len; u ++) { - x |= tmp[u] ^ ((const unsigned char *)tag)[u]; - } - return EQ0(x); -} - -/* see bearssl_aead.h */ -uint32_t -br_gcm_check_tag(br_gcm_context *ctx, const void *tag) -{ - return br_gcm_check_tag_trunc(ctx, tag, 16); -} - -/* see bearssl_aead.h */ -const br_aead_class br_gcm_vtable = { - 16, - (void (*)(const br_aead_class **, const void *, size_t)) - &br_gcm_reset, - (void (*)(const br_aead_class **, const void *, size_t)) - &br_gcm_aad_inject, - (void (*)(const br_aead_class **)) - &br_gcm_flip, - (void (*)(const br_aead_class **, int, void *, size_t)) - &br_gcm_run, - (void (*)(const br_aead_class **, void *)) - &br_gcm_get_tag, - (uint32_t (*)(const br_aead_class **, const void *)) - &br_gcm_check_tag, - (void (*)(const br_aead_class **, void *, size_t)) - &br_gcm_get_tag_trunc, - (uint32_t (*)(const br_aead_class **, const void *, size_t)) - &br_gcm_check_tag_trunc -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ghash_ctmul.c b/src/tls/bearssl/ghash_ctmul.c deleted file mode 100644 index ddb8300a6..000000000 --- a/src/tls/bearssl/ghash_ctmul.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * We compute "carryless multiplications" through normal integer - * multiplications, masking out enough bits to create "holes" in which - * carries may expand without altering our bits; we really use 8 data - * bits per 32-bit word, spaced every fourth bit. Accumulated carries - * may not exceed 8 in total, which fits in 4 bits. - * - * It would be possible to use a 3-bit spacing, allowing two operands, - * one with 7 non-zero data bits, the other one with 10 or 11 non-zero - * data bits; this asymmetric splitting makes the overall code more - * complex with thresholds and exceptions, and does not appear to be - * worth the effort. - */ - -/* - * We cannot really autodetect whether multiplications are "slow" or - * not. A typical example is the ARM Cortex M0+, which exists in two - * versions: one with a 1-cycle multiplication opcode, the other with - * a 32-cycle multiplication opcode. They both use exactly the same - * architecture and ABI, and cannot be distinguished from each other - * at compile-time. - * - * Since most modern CPU (even embedded CPU) still have fast - * multiplications, we use the "fast mul" code by default. - */ - -#if BR_SLOW_MUL - -/* - * This implementation uses Karatsuba-like reduction to make fewer - * integer multiplications (9 instead of 16), at the expense of extra - * logical operations (XOR, shifts...). On modern x86 CPU that offer - * fast, pipelined multiplications, this code is about twice slower than - * the simpler code with 16 multiplications. This tendency may be - * reversed on low-end platforms with expensive multiplications. - */ - -#define MUL32(h, l, x, y) do { \ - uint64_t mul32tmp = MUL(x, y); \ - (h) = (uint32_t)(mul32tmp >> 32); \ - (l) = (uint32_t)mul32tmp; \ - } while (0) - -static inline void -bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) -{ - uint32_t x0, x1, x2, x3; - uint32_t y0, y1, y2, y3; - uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8; - uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8; - - x0 = x & (uint32_t)0x11111111; - x1 = x & (uint32_t)0x22222222; - x2 = x & (uint32_t)0x44444444; - x3 = x & (uint32_t)0x88888888; - y0 = y & (uint32_t)0x11111111; - y1 = y & (uint32_t)0x22222222; - y2 = y & (uint32_t)0x44444444; - y3 = y & (uint32_t)0x88888888; - - /* - * (x0+W*x1)*(y0+W*y1) -> a0:b0 - * (x2+W*x3)*(y2+W*y3) -> a3:b3 - * ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6 - */ - a0 = x0; - b0 = y0; - a1 = x1 >> 1; - b1 = y1 >> 1; - a2 = a0 ^ a1; - b2 = b0 ^ b1; - a3 = x2 >> 2; - b3 = y2 >> 2; - a4 = x3 >> 3; - b4 = y3 >> 3; - a5 = a3 ^ a4; - b5 = b3 ^ b4; - a6 = a0 ^ a3; - b6 = b0 ^ b3; - a7 = a1 ^ a4; - b7 = b1 ^ b4; - a8 = a6 ^ a7; - b8 = b6 ^ b7; - - MUL32(b0, a0, b0, a0); - MUL32(b1, a1, b1, a1); - MUL32(b2, a2, b2, a2); - MUL32(b3, a3, b3, a3); - MUL32(b4, a4, b4, a4); - MUL32(b5, a5, b5, a5); - MUL32(b6, a6, b6, a6); - MUL32(b7, a7, b7, a7); - MUL32(b8, a8, b8, a8); - - a0 &= (uint32_t)0x11111111; - a1 &= (uint32_t)0x11111111; - a2 &= (uint32_t)0x11111111; - a3 &= (uint32_t)0x11111111; - a4 &= (uint32_t)0x11111111; - a5 &= (uint32_t)0x11111111; - a6 &= (uint32_t)0x11111111; - a7 &= (uint32_t)0x11111111; - a8 &= (uint32_t)0x11111111; - b0 &= (uint32_t)0x11111111; - b1 &= (uint32_t)0x11111111; - b2 &= (uint32_t)0x11111111; - b3 &= (uint32_t)0x11111111; - b4 &= (uint32_t)0x11111111; - b5 &= (uint32_t)0x11111111; - b6 &= (uint32_t)0x11111111; - b7 &= (uint32_t)0x11111111; - b8 &= (uint32_t)0x11111111; - - a2 ^= a0 ^ a1; - b2 ^= b0 ^ b1; - a0 ^= (a2 << 1) ^ (a1 << 2); - b0 ^= (b2 << 1) ^ (b1 << 2); - a5 ^= a3 ^ a4; - b5 ^= b3 ^ b4; - a3 ^= (a5 << 1) ^ (a4 << 2); - b3 ^= (b5 << 1) ^ (b4 << 2); - a8 ^= a6 ^ a7; - b8 ^= b6 ^ b7; - a6 ^= (a8 << 1) ^ (a7 << 2); - b6 ^= (b8 << 1) ^ (b7 << 2); - a6 ^= a0 ^ a3; - b6 ^= b0 ^ b3; - *lo = a0 ^ (a6 << 2) ^ (a3 << 4); - *hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28); -} - -#else - -/* - * Simple multiplication in GF(2)[X], using 16 integer multiplications. - */ - -static inline void -bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) -{ - uint32_t x0, x1, x2, x3; - uint32_t y0, y1, y2, y3; - uint64_t z0, z1, z2, z3; - uint64_t z; - - x0 = x & (uint32_t)0x11111111; - x1 = x & (uint32_t)0x22222222; - x2 = x & (uint32_t)0x44444444; - x3 = x & (uint32_t)0x88888888; - y0 = y & (uint32_t)0x11111111; - y1 = y & (uint32_t)0x22222222; - y2 = y & (uint32_t)0x44444444; - y3 = y & (uint32_t)0x88888888; - z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1); - z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2); - z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3); - z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0); - z0 &= (uint64_t)0x1111111111111111; - z1 &= (uint64_t)0x2222222222222222; - z2 &= (uint64_t)0x4444444444444444; - z3 &= (uint64_t)0x8888888888888888; - z = z0 | z1 | z2 | z3; - *lo = (uint32_t)z; - *hi = (uint32_t)(z >> 32); -} - -#endif - -/* see bearssl_hash.h */ -void -br_ghash_ctmul(void *y, const void *h, const void *data, size_t len) -{ - const unsigned char *buf, *hb; - unsigned char *yb; - uint32_t yw[4]; - uint32_t hw[4]; - - /* - * Throughout the loop we handle the y and h values as arrays - * of 32-bit words. - */ - buf = data; - yb = y; - hb = h; - yw[3] = br_dec32be(yb); - yw[2] = br_dec32be(yb + 4); - yw[1] = br_dec32be(yb + 8); - yw[0] = br_dec32be(yb + 12); - hw[3] = br_dec32be(hb); - hw[2] = br_dec32be(hb + 4); - hw[1] = br_dec32be(hb + 8); - hw[0] = br_dec32be(hb + 12); - while (len > 0) { - const unsigned char *src; - unsigned char tmp[16]; - int i; - uint32_t a[9], b[9], zw[8]; - uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3; - - /* - * Get the next 16-byte block (using zero-padding if - * necessary). - */ - if (len >= 16) { - src = buf; - buf += 16; - len -= 16; - } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - src = tmp; - len = 0; - } - - /* - * Decode the block. The GHASH standard mandates - * big-endian encoding. - */ - yw[3] ^= br_dec32be(src); - yw[2] ^= br_dec32be(src + 4); - yw[1] ^= br_dec32be(src + 8); - yw[0] ^= br_dec32be(src + 12); - - /* - * We multiply two 128-bit field elements. We use - * Karatsuba to turn that into three 64-bit - * multiplications, which are themselves done with a - * total of nine 32-bit multiplications. - */ - - /* - * y[0,1]*h[0,1] -> 0..2 - * y[2,3]*h[2,3] -> 3..5 - * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8 - */ - a[0] = yw[0]; - b[0] = hw[0]; - a[1] = yw[1]; - b[1] = hw[1]; - a[2] = a[0] ^ a[1]; - b[2] = b[0] ^ b[1]; - - a[3] = yw[2]; - b[3] = hw[2]; - a[4] = yw[3]; - b[4] = hw[3]; - a[5] = a[3] ^ a[4]; - b[5] = b[3] ^ b[4]; - - a[6] = a[0] ^ a[3]; - b[6] = b[0] ^ b[3]; - a[7] = a[1] ^ a[4]; - b[7] = b[1] ^ b[4]; - a[8] = a[6] ^ a[7]; - b[8] = b[6] ^ b[7]; - - for (i = 0; i < 9; i ++) { - bmul(&b[i], &a[i], b[i], a[i]); - } - - c0 = a[0]; - c1 = b[0] ^ a[2] ^ a[0] ^ a[1]; - c2 = a[1] ^ b[2] ^ b[0] ^ b[1]; - c3 = b[1]; - d0 = a[3]; - d1 = b[3] ^ a[5] ^ a[3] ^ a[4]; - d2 = a[4] ^ b[5] ^ b[3] ^ b[4]; - d3 = b[4]; - e0 = a[6]; - e1 = b[6] ^ a[8] ^ a[6] ^ a[7]; - e2 = a[7] ^ b[8] ^ b[6] ^ b[7]; - e3 = b[7]; - - e0 ^= c0 ^ d0; - e1 ^= c1 ^ d1; - e2 ^= c2 ^ d2; - e3 ^= c3 ^ d3; - c2 ^= e0; - c3 ^= e1; - d0 ^= e2; - d1 ^= e3; - - /* - * GHASH specification has the bits "reversed" (most - * significant is in fact least significant), which does - * not matter for a carryless multiplication, except that - * the 255-bit result must be shifted by 1 bit. - */ - zw[0] = c0 << 1; - zw[1] = (c1 << 1) | (c0 >> 31); - zw[2] = (c2 << 1) | (c1 >> 31); - zw[3] = (c3 << 1) | (c2 >> 31); - zw[4] = (d0 << 1) | (c3 >> 31); - zw[5] = (d1 << 1) | (d0 >> 31); - zw[6] = (d2 << 1) | (d1 >> 31); - zw[7] = (d3 << 1) | (d2 >> 31); - - /* - * We now do the reduction modulo the field polynomial - * to get back to 128 bits. - */ - for (i = 0; i < 4; i ++) { - uint32_t lw; - - lw = zw[i]; - zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); - zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); - } - memcpy(yw, zw + 4, sizeof yw); - } - - /* - * Encode back the result. - */ - br_enc32be(yb, yw[3]); - br_enc32be(yb + 4, yw[2]); - br_enc32be(yb + 8, yw[1]); - br_enc32be(yb + 12, yw[0]); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ghash_ctmul32.c b/src/tls/bearssl/ghash_ctmul32.c deleted file mode 100644 index 638c5aa5a..000000000 --- a/src/tls/bearssl/ghash_ctmul32.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * This implementation uses 32-bit multiplications, and only the low - * 32 bits for each multiplication result. This is meant primarily for - * the ARM Cortex M0 and M0+, whose multiplication opcode does not yield - * the upper 32 bits; but it might also be useful on architectures where - * access to the upper 32 bits requires use of specific registers that - * create contention (e.g. on i386, "mul" necessarily outputs the result - * in edx:eax, while "imul" can use any registers but is limited to the - * low 32 bits). - * - * The implementation trick that is used here is bit-reversing (bit 0 - * is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X], - * for all values x and y, we have: - * rev32(x) * rev32(y) = rev64(x * y) - * In other words, if we bit-reverse (over 32 bits) the operands, then we - * bit-reverse (over 64 bits) the result. - */ - -/* - * Multiplication in GF(2)[X], truncated to its low 32 bits. - */ -static inline uint32_t -bmul32(uint32_t x, uint32_t y) -{ - uint32_t x0, x1, x2, x3; - uint32_t y0, y1, y2, y3; - uint32_t z0, z1, z2, z3; - - x0 = x & (uint32_t)0x11111111; - x1 = x & (uint32_t)0x22222222; - x2 = x & (uint32_t)0x44444444; - x3 = x & (uint32_t)0x88888888; - y0 = y & (uint32_t)0x11111111; - y1 = y & (uint32_t)0x22222222; - y2 = y & (uint32_t)0x44444444; - y3 = y & (uint32_t)0x88888888; - z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); - z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); - z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); - z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); - z0 &= (uint32_t)0x11111111; - z1 &= (uint32_t)0x22222222; - z2 &= (uint32_t)0x44444444; - z3 &= (uint32_t)0x88888888; - return z0 | z1 | z2 | z3; -} - -/* - * Bit-reverse a 32-bit word. - */ -static uint32_t -rev32(uint32_t x) -{ -#define RMS(m, s) do { \ - x = ((x & (uint32_t)(m)) << (s)) \ - | ((x >> (s)) & (uint32_t)(m)); \ - } while (0) - - RMS(0x55555555, 1); - RMS(0x33333333, 2); - RMS(0x0F0F0F0F, 4); - RMS(0x00FF00FF, 8); - return (x << 16) | (x >> 16); - -#undef RMS -} - -/* see bearssl_hash.h */ -void -br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len) -{ - /* - * This implementation is similar to br_ghash_ctmul() except - * that we have to do the multiplication twice, with the - * "normal" and "bit reversed" operands. Hence we end up with - * eighteen 32-bit multiplications instead of nine. - */ - - const unsigned char *buf, *hb; - unsigned char *yb; - uint32_t yw[4]; - uint32_t hw[4], hwr[4]; - - buf = data; - yb = y; - hb = h; - yw[3] = br_dec32be(yb); - yw[2] = br_dec32be(yb + 4); - yw[1] = br_dec32be(yb + 8); - yw[0] = br_dec32be(yb + 12); - hw[3] = br_dec32be(hb); - hw[2] = br_dec32be(hb + 4); - hw[1] = br_dec32be(hb + 8); - hw[0] = br_dec32be(hb + 12); - hwr[3] = rev32(hw[3]); - hwr[2] = rev32(hw[2]); - hwr[1] = rev32(hw[1]); - hwr[0] = rev32(hw[0]); - while (len > 0) { - const unsigned char *src; - unsigned char tmp[16]; - int i; - uint32_t a[18], b[18], c[18]; - uint32_t d0, d1, d2, d3, d4, d5, d6, d7; - uint32_t zw[8]; - - if (len >= 16) { - src = buf; - buf += 16; - len -= 16; - } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - src = tmp; - len = 0; - } - yw[3] ^= br_dec32be(src); - yw[2] ^= br_dec32be(src + 4); - yw[1] ^= br_dec32be(src + 8); - yw[0] ^= br_dec32be(src + 12); - - /* - * We are using Karatsuba: the 128x128 multiplication is - * reduced to three 64x64 multiplications, hence nine - * 32x32 multiplications. With the bit-reversal trick, - * we have to perform 18 32x32 multiplications. - */ - - /* - * y[0,1]*h[0,1] -> 0,1,4 - * y[2,3]*h[2,3] -> 2,3,5 - * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8 - */ - - a[0] = yw[0]; - a[1] = yw[1]; - a[2] = yw[2]; - a[3] = yw[3]; - a[4] = a[0] ^ a[1]; - a[5] = a[2] ^ a[3]; - a[6] = a[0] ^ a[2]; - a[7] = a[1] ^ a[3]; - a[8] = a[6] ^ a[7]; - - a[ 9] = rev32(yw[0]); - a[10] = rev32(yw[1]); - a[11] = rev32(yw[2]); - a[12] = rev32(yw[3]); - a[13] = a[ 9] ^ a[10]; - a[14] = a[11] ^ a[12]; - a[15] = a[ 9] ^ a[11]; - a[16] = a[10] ^ a[12]; - a[17] = a[15] ^ a[16]; - - b[0] = hw[0]; - b[1] = hw[1]; - b[2] = hw[2]; - b[3] = hw[3]; - b[4] = b[0] ^ b[1]; - b[5] = b[2] ^ b[3]; - b[6] = b[0] ^ b[2]; - b[7] = b[1] ^ b[3]; - b[8] = b[6] ^ b[7]; - - b[ 9] = hwr[0]; - b[10] = hwr[1]; - b[11] = hwr[2]; - b[12] = hwr[3]; - b[13] = b[ 9] ^ b[10]; - b[14] = b[11] ^ b[12]; - b[15] = b[ 9] ^ b[11]; - b[16] = b[10] ^ b[12]; - b[17] = b[15] ^ b[16]; - - for (i = 0; i < 18; i ++) { - c[i] = bmul32(a[i], b[i]); - } - - c[4] ^= c[0] ^ c[1]; - c[5] ^= c[2] ^ c[3]; - c[8] ^= c[6] ^ c[7]; - - c[13] ^= c[ 9] ^ c[10]; - c[14] ^= c[11] ^ c[12]; - c[17] ^= c[15] ^ c[16]; - - /* - * y[0,1]*h[0,1] -> 0,9^4,1^13,10 - * y[2,3]*h[2,3] -> 2,11^5,3^14,12 - * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16 - */ - d0 = c[0]; - d1 = c[4] ^ (rev32(c[9]) >> 1); - d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1); - d3 = c[4] ^ c[5] ^ c[8] - ^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1); - d4 = c[2] ^ c[1] ^ c[3] ^ c[7] - ^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1); - d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1); - d6 = c[3] ^ (rev32(c[14]) >> 1); - d7 = rev32(c[12]) >> 1; - - zw[0] = d0 << 1; - zw[1] = (d1 << 1) | (d0 >> 31); - zw[2] = (d2 << 1) | (d1 >> 31); - zw[3] = (d3 << 1) | (d2 >> 31); - zw[4] = (d4 << 1) | (d3 >> 31); - zw[5] = (d5 << 1) | (d4 >> 31); - zw[6] = (d6 << 1) | (d5 >> 31); - zw[7] = (d7 << 1) | (d6 >> 31); - - for (i = 0; i < 4; i ++) { - uint32_t lw; - - lw = zw[i]; - zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); - zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); - } - memcpy(yw, zw + 4, sizeof yw); - } - br_enc32be(yb, yw[3]); - br_enc32be(yb + 4, yw[2]); - br_enc32be(yb + 8, yw[1]); - br_enc32be(yb + 12, yw[0]); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ghash_ctmul64.c b/src/tls/bearssl/ghash_ctmul64.c deleted file mode 100644 index b3902d10a..000000000 --- a/src/tls/bearssl/ghash_ctmul64.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands - * and bit reversal of 64-bit words. - */ - -static inline uint64_t -bmul64(uint64_t x, uint64_t y) -{ - uint64_t x0, x1, x2, x3; - uint64_t y0, y1, y2, y3; - uint64_t z0, z1, z2, z3; - - x0 = x & (uint64_t)0x1111111111111111; - x1 = x & (uint64_t)0x2222222222222222; - x2 = x & (uint64_t)0x4444444444444444; - x3 = x & (uint64_t)0x8888888888888888; - y0 = y & (uint64_t)0x1111111111111111; - y1 = y & (uint64_t)0x2222222222222222; - y2 = y & (uint64_t)0x4444444444444444; - y3 = y & (uint64_t)0x8888888888888888; - z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); - z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); - z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); - z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); - z0 &= (uint64_t)0x1111111111111111; - z1 &= (uint64_t)0x2222222222222222; - z2 &= (uint64_t)0x4444444444444444; - z3 &= (uint64_t)0x8888888888888888; - return z0 | z1 | z2 | z3; -} - -static uint64_t -rev64(uint64_t x) -{ -#define RMS(m, s) do { \ - x = ((x & (uint64_t)(m)) << (s)) \ - | ((x >> (s)) & (uint64_t)(m)); \ - } while (0) - - RMS(0x5555555555555555, 1); - RMS(0x3333333333333333, 2); - RMS(0x0F0F0F0F0F0F0F0F, 4); - RMS(0x00FF00FF00FF00FF, 8); - RMS(0x0000FFFF0000FFFF, 16); - return (x << 32) | (x >> 32); - -#undef RMS -} - -/* see bearssl_ghash.h */ -void -br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len) -{ - const unsigned char *buf, *hb; - unsigned char *yb; - uint64_t y0, y1; - uint64_t h0, h1, h2, h0r, h1r, h2r; - - buf = data; - yb = y; - hb = h; - y1 = br_dec64be(yb); - y0 = br_dec64be(yb + 8); - h1 = br_dec64be(hb); - h0 = br_dec64be(hb + 8); - h0r = rev64(h0); - h1r = rev64(h1); - h2 = h0 ^ h1; - h2r = h0r ^ h1r; - while (len > 0) { - const unsigned char *src; - unsigned char tmp[16]; - uint64_t y0r, y1r, y2, y2r; - uint64_t z0, z1, z2, z0h, z1h, z2h; - uint64_t v0, v1, v2, v3; - - if (len >= 16) { - src = buf; - buf += 16; - len -= 16; - } else { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - src = tmp; - len = 0; - } - y1 ^= br_dec64be(src); - y0 ^= br_dec64be(src + 8); - - y0r = rev64(y0); - y1r = rev64(y1); - y2 = y0 ^ y1; - y2r = y0r ^ y1r; - - z0 = bmul64(y0, h0); - z1 = bmul64(y1, h1); - z2 = bmul64(y2, h2); - z0h = bmul64(y0r, h0r); - z1h = bmul64(y1r, h1r); - z2h = bmul64(y2r, h2r); - z2 ^= z0 ^ z1; - z2h ^= z0h ^ z1h; - z0h = rev64(z0h) >> 1; - z1h = rev64(z1h) >> 1; - z2h = rev64(z2h) >> 1; - - v0 = z0; - v1 = z0h ^ z2; - v2 = z1 ^ z2h; - v3 = z1h; - - v3 = (v3 << 1) | (v2 >> 63); - v2 = (v2 << 1) | (v1 >> 63); - v1 = (v1 << 1) | (v0 >> 63); - v0 = (v0 << 1); - - v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); - v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); - v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); - v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); - - y0 = v2; - y1 = v3; - } - - br_enc64be(yb, y1); - br_enc64be(yb + 8, y0); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ghash_pclmul.c b/src/tls/bearssl/ghash_pclmul.c deleted file mode 100644 index f8a7077f8..000000000 --- a/src/tls/bearssl/ghash_pclmul.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_ENABLE_INTRINSICS 1 -#include "inner.h" - -/* - * This is the GHASH implementation that leverages the pclmulqdq opcode - * (from the AES-NI instructions). - */ - -#if BR_AES_X86NI - -/* - * Test CPU support for PCLMULQDQ. - */ -static inline int -pclmul_supported(void) -{ - /* - * Bit mask for features in ECX: - * 1 PCLMULQDQ support - */ - return br_cpuid(0, 0, 0x00000002, 0); -} - -/* see bearssl_hash.h */ -br_ghash -br_ghash_pclmul_get(void) -{ - return pclmul_supported() ? &br_ghash_pclmul : 0; -} - -BR_TARGETS_X86_UP - -/* - * GHASH is defined over elements of GF(2^128) with "full little-endian" - * representation: leftmost byte is least significant, and, within each - * byte, leftmost _bit_ is least significant. The natural ordering in - * x86 is "mixed little-endian": bytes are ordered from least to most - * significant, but bits within a byte are in most-to-least significant - * order. Going to full little-endian representation would require - * reversing bits within each byte, which is doable but expensive. - * - * Instead, we go to full big-endian representation, by swapping bytes - * around, which is done with a single _mm_shuffle_epi8() opcode (it - * comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We - * can use a full big-endian representation because in a carryless - * multiplication, we have a nice bit reversal property: - * - * rev_128(x) * rev_128(y) = rev_255(x * y) - * - * So by using full big-endian, we still get the right result, except - * that it is right-shifted by 1 bit. The left-shift is relatively - * inexpensive, and it can be mutualised. - * - * - * Since SSE2 opcodes do not have facilities for shitfting full 128-bit - * values with bit precision, we have to break down values into 64-bit - * chunks. We number chunks from 0 to 3 in left to right order. - */ - -/* - * Byte-swap a complete 128-bit value. This normally uses - * _mm_shuffle_epi8(), which gets translated to pshufb (an SSSE3 opcode). - * However, this crashes old Clang versions, so, for Clang before 3.8, - * we use an alternate (and less efficient) version. - */ -#if BR_CLANG && !BR_CLANG_3_8 -#define BYTESWAP_DECL -#define BYTESWAP_PREP (void)0 -#define BYTESWAP(x) do { \ - __m128i byteswap1, byteswap2; \ - byteswap1 = (x); \ - byteswap2 = _mm_srli_epi16(byteswap1, 8); \ - byteswap1 = _mm_slli_epi16(byteswap1, 8); \ - byteswap1 = _mm_or_si128(byteswap1, byteswap2); \ - byteswap1 = _mm_shufflelo_epi16(byteswap1, 0x1B); \ - byteswap1 = _mm_shufflehi_epi16(byteswap1, 0x1B); \ - (x) = _mm_shuffle_epi32(byteswap1, 0x4E); \ - } while (0) -#else -#define BYTESWAP_DECL __m128i byteswap_index; -#define BYTESWAP_PREP do { \ - byteswap_index = _mm_set_epi8( \ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \ - } while (0) -#define BYTESWAP(x) do { \ - (x) = _mm_shuffle_epi8((x), byteswap_index); \ - } while (0) -#endif - -/* - * Call pclmulqdq. Clang appears to have trouble with the intrinsic, so, - * for that compiler, we use inline assembly. Inline assembly is - * potentially a bit slower because the compiler does not understand - * what the opcode does, and thus cannot optimize instruction - * scheduling. - * - * We use a target of "sse2" only, so that Clang may still handle the - * '__m128i' type and allocate SSE2 registers. - */ -#if BR_CLANG -BR_TARGET("sse2") -static inline __m128i -pclmulqdq00(__m128i x, __m128i y) -{ - __asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y)); - return x; -} -BR_TARGET("sse2") -static inline __m128i -pclmulqdq11(__m128i x, __m128i y) -{ - __asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y)); - return x; -} -#else -#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00) -#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11) -#endif - -/* - * From a 128-bit value kw, compute kx as the XOR of the two 64-bit - * halves of kw (into the right half of kx; left half is unspecified). - */ -#define BK(kw, kx) do { \ - kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \ - } while (0) - -/* - * Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and - * the XOR of the two values (kx). - */ -#define PBK(k0, k1, kw, kx) do { \ - kw = _mm_unpacklo_epi64(k1, k0); \ - kx = _mm_xor_si128(k0, k1); \ - } while (0) - -/* - * Left-shift by 1 bit a 256-bit value (in four 64-bit words). - */ -#define SL_256(x0, x1, x2, x3) do { \ - x0 = _mm_or_si128( \ - _mm_slli_epi64(x0, 1), \ - _mm_srli_epi64(x1, 63)); \ - x1 = _mm_or_si128( \ - _mm_slli_epi64(x1, 1), \ - _mm_srli_epi64(x2, 63)); \ - x2 = _mm_or_si128( \ - _mm_slli_epi64(x2, 1), \ - _mm_srli_epi64(x3, 63)); \ - x3 = _mm_slli_epi64(x3, 1); \ - } while (0) - -/* - * Perform reduction in GF(2^128). The 256-bit value is in x0..x3; - * result is written in x0..x1. - */ -#define REDUCE_F128(x0, x1, x2, x3) do { \ - x1 = _mm_xor_si128( \ - x1, \ - _mm_xor_si128( \ - _mm_xor_si128( \ - x3, \ - _mm_srli_epi64(x3, 1)), \ - _mm_xor_si128( \ - _mm_srli_epi64(x3, 2), \ - _mm_srli_epi64(x3, 7)))); \ - x2 = _mm_xor_si128( \ - _mm_xor_si128( \ - x2, \ - _mm_slli_epi64(x3, 63)), \ - _mm_xor_si128( \ - _mm_slli_epi64(x3, 62), \ - _mm_slli_epi64(x3, 57))); \ - x0 = _mm_xor_si128( \ - x0, \ - _mm_xor_si128( \ - _mm_xor_si128( \ - x2, \ - _mm_srli_epi64(x2, 1)), \ - _mm_xor_si128( \ - _mm_srli_epi64(x2, 2), \ - _mm_srli_epi64(x2, 7)))); \ - x1 = _mm_xor_si128( \ - _mm_xor_si128( \ - x1, \ - _mm_slli_epi64(x2, 63)), \ - _mm_xor_si128( \ - _mm_slli_epi64(x2, 62), \ - _mm_slli_epi64(x2, 57))); \ - } while (0) - -/* - * Square value kw into (dw,dx). - */ -#define SQUARE_F128(kw, dw, dx) do { \ - __m128i z0, z1, z2, z3; \ - z1 = pclmulqdq11(kw, kw); \ - z3 = pclmulqdq00(kw, kw); \ - z0 = _mm_shuffle_epi32(z1, 0x0E); \ - z2 = _mm_shuffle_epi32(z3, 0x0E); \ - SL_256(z0, z1, z2, z3); \ - REDUCE_F128(z0, z1, z2, z3); \ - PBK(z0, z1, dw, dx); \ - } while (0) - -/* see bearssl_hash.h */ -BR_TARGET("ssse3,pclmul") -void -br_ghash_pclmul(void *y, const void *h, const void *data, size_t len) -{ - const unsigned char *buf1, *buf2; - unsigned char tmp[64]; - size_t num4, num1; - __m128i yw, h1w, h1x; - BYTESWAP_DECL - - /* - * We split data into two chunks. First chunk starts at buf1 - * and contains num4 blocks of 64-byte values. Second chunk - * starts at buf2 and contains num1 blocks of 16-byte values. - * We want the first chunk to be as large as possible. - */ - buf1 = data; - num4 = len >> 6; - len &= 63; - buf2 = buf1 + (num4 << 6); - num1 = (len + 15) >> 4; - if ((len & 15) != 0) { - memcpy(tmp, buf2, len); - memset(tmp + len, 0, (num1 << 4) - len); - buf2 = tmp; - } - - /* - * Preparatory step for endian conversions. - */ - BYTESWAP_PREP; - - /* - * Load y and h. - */ - yw = _mm_loadu_si128(y); - h1w = _mm_loadu_si128(h); - BYTESWAP(yw); - BYTESWAP(h1w); - BK(h1w, h1x); - - if (num4 > 0) { - __m128i h2w, h2x, h3w, h3x, h4w, h4x; - __m128i t0, t1, t2, t3; - - /* - * Compute h2 = h^2. - */ - SQUARE_F128(h1w, h2w, h2x); - - /* - * Compute h3 = h^3 = h*(h^2). - */ - t1 = pclmulqdq11(h1w, h2w); - t3 = pclmulqdq00(h1w, h2w); - t2 = _mm_xor_si128(pclmulqdq00(h1x, h2x), - _mm_xor_si128(t1, t3)); - t0 = _mm_shuffle_epi32(t1, 0x0E); - t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); - t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); - SL_256(t0, t1, t2, t3); - REDUCE_F128(t0, t1, t2, t3); - PBK(t0, t1, h3w, h3x); - - /* - * Compute h4 = h^4 = (h^2)^2. - */ - SQUARE_F128(h2w, h4w, h4x); - - while (num4 -- > 0) { - __m128i aw0, aw1, aw2, aw3; - __m128i ax0, ax1, ax2, ax3; - - aw0 = _mm_loadu_si128((void *)(buf1 + 0)); - aw1 = _mm_loadu_si128((void *)(buf1 + 16)); - aw2 = _mm_loadu_si128((void *)(buf1 + 32)); - aw3 = _mm_loadu_si128((void *)(buf1 + 48)); - BYTESWAP(aw0); - BYTESWAP(aw1); - BYTESWAP(aw2); - BYTESWAP(aw3); - buf1 += 64; - - aw0 = _mm_xor_si128(aw0, yw); - BK(aw1, ax1); - BK(aw2, ax2); - BK(aw3, ax3); - BK(aw0, ax0); - - t1 = _mm_xor_si128( - _mm_xor_si128( - pclmulqdq11(aw0, h4w), - pclmulqdq11(aw1, h3w)), - _mm_xor_si128( - pclmulqdq11(aw2, h2w), - pclmulqdq11(aw3, h1w))); - t3 = _mm_xor_si128( - _mm_xor_si128( - pclmulqdq00(aw0, h4w), - pclmulqdq00(aw1, h3w)), - _mm_xor_si128( - pclmulqdq00(aw2, h2w), - pclmulqdq00(aw3, h1w))); - t2 = _mm_xor_si128( - _mm_xor_si128( - pclmulqdq00(ax0, h4x), - pclmulqdq00(ax1, h3x)), - _mm_xor_si128( - pclmulqdq00(ax2, h2x), - pclmulqdq00(ax3, h1x))); - t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); - t0 = _mm_shuffle_epi32(t1, 0x0E); - t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); - t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); - SL_256(t0, t1, t2, t3); - REDUCE_F128(t0, t1, t2, t3); - yw = _mm_unpacklo_epi64(t1, t0); - } - } - - while (num1 -- > 0) { - __m128i aw, ax; - __m128i t0, t1, t2, t3; - - aw = _mm_loadu_si128((void *)buf2); - BYTESWAP(aw); - buf2 += 16; - - aw = _mm_xor_si128(aw, yw); - BK(aw, ax); - - t1 = pclmulqdq11(aw, h1w); - t3 = pclmulqdq00(aw, h1w); - t2 = pclmulqdq00(ax, h1x); - t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); - t0 = _mm_shuffle_epi32(t1, 0x0E); - t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); - t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); - SL_256(t0, t1, t2, t3); - REDUCE_F128(t0, t1, t2, t3); - yw = _mm_unpacklo_epi64(t1, t0); - } - - BYTESWAP(yw); - _mm_storeu_si128(y, yw); -} - -BR_TARGETS_X86_DOWN - -#else - -/* see bearssl_hash.h */ -br_ghash -br_ghash_pclmul_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ghash_pwr8.c b/src/tls/bearssl/ghash_pwr8.c deleted file mode 100644 index 9d07ded21..000000000 --- a/src/tls/bearssl/ghash_pwr8.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_POWER_ASM_MACROS 1 -#include "inner.h" - -/* - * This is the GHASH implementation that leverages the POWER8 opcodes. - */ - -#if BR_POWER8 - -/* - * Some symbolic names for registers. - * HB0 = 16 bytes of value 0 - * HB1 = 16 bytes of value 1 - * HB2 = 16 bytes of value 2 - * HB6 = 16 bytes of value 6 - * HB7 = 16 bytes of value 7 - * TT0, TT1 and TT2 are temporaries - * - * BSW holds the pattern for byteswapping 32-bit words; this is set only - * on little-endian systems. XBSW is the same register with the +32 offset - * for access with the VSX opcodes. - */ -#define HB0 0 -#define HB1 1 -#define HB2 2 -#define HB6 3 -#define HB7 4 -#define TT0 5 -#define TT1 6 -#define TT2 7 - -#define BSW 8 -#define XBSW 40 - -/* - * Macro to initialise the constants. - */ -#define INIT \ - vxor(HB0, HB0, HB0) \ - vspltisb(HB1, 1) \ - vspltisb(HB2, 2) \ - vspltisb(HB6, 6) \ - vspltisb(HB7, 7) \ - INIT_BSW - -/* - * Fix endianness of a value after reading it or before writing it, if - * necessary. - */ -#if BR_POWER8_LE -#define INIT_BSW lxvw4x(XBSW, 0, %[idx2be]) -#define FIX_ENDIAN(xx) vperm(xx, xx, xx, BSW) -#else -#define INIT_BSW -#define FIX_ENDIAN(xx) -#endif - -/* - * Left-shift x0:x1 by one bit to the left. This is a corrective action - * needed because GHASH is defined in full little-endian specification, - * while the opcodes use full big-endian convention, so the 255-bit product - * ends up one bit to the right. - */ -#define SL_256(x0, x1) \ - vsldoi(TT0, HB0, x1, 1) \ - vsl(x0, x0, HB1) \ - vsr(TT0, TT0, HB7) \ - vsl(x1, x1, HB1) \ - vxor(x0, x0, TT0) - -/* - * Reduce x0:x1 in GF(2^128), result in xd (register xd may be the same as - * x0 or x1, or a different register). x0 and x1 are modified. - */ -#define REDUCE_F128(xd, x0, x1) \ - vxor(x0, x0, x1) \ - vsr(TT0, x1, HB1) \ - vsr(TT1, x1, HB2) \ - vsr(TT2, x1, HB7) \ - vxor(x0, x0, TT0) \ - vxor(TT1, TT1, TT2) \ - vxor(x0, x0, TT1) \ - vsldoi(x1, x1, HB0, 15) \ - vsl(TT1, x1, HB6) \ - vsl(TT2, x1, HB1) \ - vxor(x1, TT1, TT2) \ - vsr(TT0, x1, HB1) \ - vsr(TT1, x1, HB2) \ - vsr(TT2, x1, HB7) \ - vxor(x0, x0, x1) \ - vxor(x0, x0, TT0) \ - vxor(TT1, TT1, TT2) \ - vxor(xd, x0, TT1) - -/* see bearssl_hash.h */ -void -br_ghash_pwr8(void *y, const void *h, const void *data, size_t len) -{ - const unsigned char *buf1, *buf2; - size_t num4, num1; - unsigned char tmp[64]; - long cc0, cc1, cc2, cc3; - -#if BR_POWER8_LE - static const uint32_t idx2be[] = { - 0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C - }; -#endif - - buf1 = data; - - /* - * Assembly code requires data into two chunks; first chunk - * must contain a number of blocks which is a multiple of 4. - * Since the processing for the first chunk is faster, we want - * to make it as big as possible. - * - * For the remainder, there are two possibilities: - * -- if the remainder size is a multiple of 16, then use it - * in place; - * -- otherwise, copy it to the tmp[] array and pad it with - * zeros. - */ - num4 = len >> 6; - buf2 = buf1 + (num4 << 6); - len &= 63; - num1 = (len + 15) >> 4; - if ((len & 15) != 0) { - memcpy(tmp, buf2, len); - memset(tmp + len, 0, (num1 << 4) - len); - buf2 = tmp; - } - - cc0 = 0; - cc1 = 16; - cc2 = 32; - cc3 = 48; - asm volatile ( - INIT - - /* - * Load current h (denoted hereafter h1) in v9. - */ - lxvw4x(41, 0, %[h]) - FIX_ENDIAN(9) - - /* - * Load current y into v28. - */ - lxvw4x(60, 0, %[y]) - FIX_ENDIAN(28) - - /* - * Split h1 into three registers: - * v17 = h1_1:h1_0 - * v18 = 0:h1_0 - * v19 = h1_1:0 - */ - xxpermdi(49, 41, 41, 2) - vsldoi(18, HB0, 9, 8) - vsldoi(19, 9, HB0, 8) - - /* - * If num4 is 0, skip directly to the second chunk. - */ - cmpldi(%[num4], 0) - beq(chunk1) - - /* - * Compute h2 = h*h in v10. - */ - vpmsumd(10, 18, 18) - vpmsumd(11, 19, 19) - SL_256(10, 11) - REDUCE_F128(10, 10, 11) - - /* - * Compute h3 = h*h*h in v11. - * We first split h2 into: - * v10 = h2_0:h2_1 - * v11 = 0:h2_0 - * v12 = h2_1:0 - * Then we do the product with h1, and reduce into v11. - */ - vsldoi(11, HB0, 10, 8) - vsldoi(12, 10, HB0, 8) - vpmsumd(13, 10, 17) - vpmsumd(11, 11, 18) - vpmsumd(12, 12, 19) - vsldoi(14, HB0, 13, 8) - vsldoi(15, 13, HB0, 8) - vxor(11, 11, 14) - vxor(12, 12, 15) - SL_256(11, 12) - REDUCE_F128(11, 11, 12) - - /* - * Compute h4 = h*h*h*h in v12. This is done by squaring h2. - */ - vsldoi(12, HB0, 10, 8) - vsldoi(13, 10, HB0, 8) - vpmsumd(12, 12, 12) - vpmsumd(13, 13, 13) - SL_256(12, 13) - REDUCE_F128(12, 12, 13) - - /* - * Repack h1, h2, h3 and h4: - * v13 = h4_0:h3_0 - * v14 = h4_1:h3_1 - * v15 = h2_0:h1_0 - * v16 = h2_1:h1_1 - */ - xxpermdi(45, 44, 43, 0) - xxpermdi(46, 44, 43, 3) - xxpermdi(47, 42, 41, 0) - xxpermdi(48, 42, 41, 3) - - /* - * Loop for each group of four blocks. - */ - mtctr(%[num4]) - label(loop4) - /* - * Read the four next blocks. - * v20 = y + a0 = b0 - * v21 = a1 = b1 - * v22 = a2 = b2 - * v23 = a3 = b3 - */ - lxvw4x(52, %[cc0], %[buf1]) - lxvw4x(53, %[cc1], %[buf1]) - lxvw4x(54, %[cc2], %[buf1]) - lxvw4x(55, %[cc3], %[buf1]) - FIX_ENDIAN(20) - FIX_ENDIAN(21) - FIX_ENDIAN(22) - FIX_ENDIAN(23) - addi(%[buf1], %[buf1], 64) - vxor(20, 20, 28) - - /* - * Repack the blocks into v9, v10, v11 and v12. - * v9 = b0_0:b1_0 - * v10 = b0_1:b1_1 - * v11 = b2_0:b3_0 - * v12 = b2_1:b3_1 - */ - xxpermdi(41, 52, 53, 0) - xxpermdi(42, 52, 53, 3) - xxpermdi(43, 54, 55, 0) - xxpermdi(44, 54, 55, 3) - - /* - * Compute the products. - * v20 = b0_0*h4_0 + b1_0*h3_0 - * v21 = b0_1*h4_0 + b1_1*h3_0 - * v22 = b0_0*h4_1 + b1_0*h3_1 - * v23 = b0_1*h4_1 + b1_1*h3_1 - * v24 = b2_0*h2_0 + b3_0*h1_0 - * v25 = b2_1*h2_0 + b3_1*h1_0 - * v26 = b2_0*h2_1 + b3_0*h1_1 - * v27 = b2_1*h2_1 + b3_1*h1_1 - */ - vpmsumd(20, 13, 9) - vpmsumd(21, 13, 10) - vpmsumd(22, 14, 9) - vpmsumd(23, 14, 10) - vpmsumd(24, 15, 11) - vpmsumd(25, 15, 12) - vpmsumd(26, 16, 11) - vpmsumd(27, 16, 12) - - /* - * Sum products into a single 256-bit result in v11:v12. - */ - vxor(11, 20, 24) - vxor(12, 23, 27) - vxor( 9, 21, 22) - vxor(10, 25, 26) - vxor(20, 9, 10) - vsldoi( 9, HB0, 20, 8) - vsldoi(10, 20, HB0, 8) - vxor(11, 11, 9) - vxor(12, 12, 10) - - /* - * Fix and reduce in GF(2^128); this is the new y (in v28). - */ - SL_256(11, 12) - REDUCE_F128(28, 11, 12) - - /* - * Loop for next group of four blocks. - */ - bdnz(loop4) - - /* - * Process second chunk, one block at a time. - */ - label(chunk1) - cmpldi(%[num1], 0) - beq(done) - - mtctr(%[num1]) - label(loop1) - /* - * Load next data block and XOR it into y. - */ - lxvw4x(41, 0, %[buf2]) -#if BR_POWER8_LE - FIX_ENDIAN(9) -#endif - addi(%[buf2], %[buf2], 16) - vxor(9, 28, 9) - - /* - * Split y into doublewords: - * v9 = y_0:y_1 - * v10 = 0:y_0 - * v11 = y_1:0 - */ - vsldoi(10, HB0, 9, 8) - vsldoi(11, 9, HB0, 8) - - /* - * Compute products with h: - * v12 = y_0 * h_0 - * v13 = y_1 * h_1 - * v14 = y_1 * h_0 + y_0 * h_1 - */ - vpmsumd(14, 9, 17) - vpmsumd(12, 10, 18) - vpmsumd(13, 11, 19) - - /* - * Propagate v14 into v12:v13 to finalise product. - */ - vsldoi(10, HB0, 14, 8) - vsldoi(11, 14, HB0, 8) - vxor(12, 12, 10) - vxor(13, 13, 11) - - /* - * Fix result and reduce into v28 (next value for y). - */ - SL_256(12, 13) - REDUCE_F128(28, 12, 13) - bdnz(loop1) - - label(done) - /* - * Write back the new y. - */ - FIX_ENDIAN(28) - stxvw4x(60, 0, %[y]) - -: [buf1] "+b" (buf1), [buf2] "+b" (buf2) -: [y] "b" (y), [h] "b" (h), [num4] "b" (num4), [num1] "b" (num1), - [cc0] "b" (cc0), [cc1] "b" (cc1), [cc2] "b" (cc2), [cc3] "b" (cc3) -#if BR_POWER8_LE - , [idx2be] "b" (idx2be) -#endif -: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", - "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", - "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", - "ctr", "memory" - ); -} - -/* see bearssl_hash.h */ -br_ghash -br_ghash_pwr8_get(void) -{ - return &br_ghash_pwr8; -} - -#else - -/* see bearssl_hash.h */ -br_ghash -br_ghash_pwr8_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/hkdf.c b/src/tls/bearssl/hkdf.c deleted file mode 100644 index d89d660a3..000000000 --- a/src/tls/bearssl/hkdf.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -const unsigned char br_hkdf_no_salt = 0; - -/* see bearssl_kdf.h */ -void -br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable, - const void *salt, size_t salt_len) -{ - br_hmac_key_context kc; - unsigned char tmp[64]; - - if (salt == BR_HKDF_NO_SALT) { - salt = tmp; - salt_len = br_digest_size(digest_vtable); - memset(tmp, 0, salt_len); - } - br_hmac_key_init(&kc, digest_vtable, salt, salt_len); - br_hmac_init(&hc->u.hmac_ctx, &kc, 0); - hc->dig_len = br_hmac_size(&hc->u.hmac_ctx); -} - -/* see bearssl_kdf.h */ -void -br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len) -{ - br_hmac_update(&hc->u.hmac_ctx, ikm, ikm_len); -} - -/* see bearssl_kdf.h */ -void -br_hkdf_flip(br_hkdf_context *hc) -{ - unsigned char tmp[64]; - - br_hmac_out(&hc->u.hmac_ctx, tmp); - br_hmac_key_init(&hc->u.prk_ctx, - br_hmac_get_digest(&hc->u.hmac_ctx), tmp, hc->dig_len); - hc->ptr = hc->dig_len; - hc->chunk_num = 0; -} - -/* see bearssl_kdf.h */ -size_t -br_hkdf_produce(br_hkdf_context *hc, - const void *info, size_t info_len, void *out, size_t out_len) -{ - size_t tlen; - - tlen = 0; - while (out_len > 0) { - size_t clen; - - if (hc->ptr == hc->dig_len) { - br_hmac_context hmac_ctx; - unsigned char x; - - hc->chunk_num ++; - if (hc->chunk_num == 256) { - return tlen; - } - x = hc->chunk_num; - br_hmac_init(&hmac_ctx, &hc->u.prk_ctx, 0); - if (x != 1) { - br_hmac_update(&hmac_ctx, hc->buf, hc->dig_len); - } - br_hmac_update(&hmac_ctx, info, info_len); - br_hmac_update(&hmac_ctx, &x, 1); - br_hmac_out(&hmac_ctx, hc->buf); - hc->ptr = 0; - } - clen = hc->dig_len - hc->ptr; - if (clen > out_len) { - clen = out_len; - } - memcpy(out, hc->buf + hc->ptr, clen); - out = (unsigned char *)out + clen; - out_len -= clen; - hc->ptr += clen; - tlen += clen; - } - return tlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/hmac.c b/src/tls/bearssl/hmac.c deleted file mode 100644 index 3e0cd7247..000000000 --- a/src/tls/bearssl/hmac.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static inline size_t -block_size(const br_hash_class *dig) -{ - unsigned ls; - - ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF) - & BR_HASHDESC_LBLEN_MASK; - return (size_t)1 << ls; -} - -static void -process_key(const br_hash_class **hc, void *ks, - const void *key, size_t key_len, unsigned bb) -{ - unsigned char tmp[256]; - size_t blen, u; - - blen = block_size(*hc); - memcpy(tmp, key, key_len); - for (u = 0; u < key_len; u ++) { - tmp[u] ^= (unsigned char)bb; - } - memset(tmp + key_len, bb, blen - key_len); - (*hc)->init(hc); - (*hc)->update(hc, tmp, blen); - (*hc)->state(hc, ks); -} - -/* see bearssl.h */ -void -br_hmac_key_init(br_hmac_key_context *kc, - const br_hash_class *dig, const void *key, size_t key_len) -{ - br_hash_compat_context hc; - unsigned char kbuf[64]; - - kc->dig_vtable = dig; - hc.vtable = dig; - if (key_len > block_size(dig)) { - dig->init(&hc.vtable); - dig->update(&hc.vtable, key, key_len); - dig->out(&hc.vtable, kbuf); - key = kbuf; - key_len = br_digest_size(dig); - } - process_key(&hc.vtable, kc->ksi, key, key_len, 0x36); - process_key(&hc.vtable, kc->kso, key, key_len, 0x5C); -} - -/* see bearssl.h */ -void -br_hmac_init(br_hmac_context *ctx, - const br_hmac_key_context *kc, size_t out_len) -{ - const br_hash_class *dig; - size_t blen, hlen; - - dig = kc->dig_vtable; - blen = block_size(dig); - dig->init(&ctx->dig.vtable); - dig->set_state(&ctx->dig.vtable, kc->ksi, (uint64_t)blen); - memcpy(ctx->kso, kc->kso, sizeof kc->kso); - hlen = br_digest_size(dig); - if (out_len > 0 && out_len < hlen) { - hlen = out_len; - } - ctx->out_len = hlen; -} - -/* see bearssl.h */ -void -br_hmac_update(br_hmac_context *ctx, const void *data, size_t len) -{ - ctx->dig.vtable->update(&ctx->dig.vtable, data, len); -} - -/* see bearssl.h */ -size_t -br_hmac_out(const br_hmac_context *ctx, void *out) -{ - const br_hash_class *dig; - br_hash_compat_context hc; - unsigned char tmp[64]; - size_t blen, hlen; - - dig = ctx->dig.vtable; - dig->out(&ctx->dig.vtable, tmp); - blen = block_size(dig); - dig->init(&hc.vtable); - dig->set_state(&hc.vtable, ctx->kso, (uint64_t)blen); - hlen = br_digest_size(dig); - dig->update(&hc.vtable, tmp, hlen); - dig->out(&hc.vtable, tmp); - memcpy(out, tmp, ctx->out_len); - return ctx->out_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/hmac_ct.c b/src/tls/bearssl/hmac_ct.c deleted file mode 100644 index 51560ab1d..000000000 --- a/src/tls/bearssl/hmac_ct.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static inline size_t -hash_size(const br_hash_class *dig) -{ - return (unsigned)(dig->desc >> BR_HASHDESC_OUT_OFF) - & BR_HASHDESC_OUT_MASK; -} - -static inline size_t -block_size(const br_hash_class *dig) -{ - unsigned ls; - - ls = (unsigned)(dig->desc >> BR_HASHDESC_LBLEN_OFF) - & BR_HASHDESC_LBLEN_MASK; - return (size_t)1 << ls; -} - -/* see bearssl.h */ -size_t -br_hmac_outCT(const br_hmac_context *ctx, - const void *data, size_t len, size_t min_len, size_t max_len, - void *out) -{ - /* - * Method implemented here is inspired from the descriptions on: - * https://www.imperialviolet.org/2013/02/04/luckythirteen.html - * - * Principle: we input bytes one by one. We use a MUX to push - * padding bytes instead of data bytes when appropriate. At each - * block limit, we get the current hash function state: this is - * a potential output, since we handle MD padding ourselves. - * - * be 1 for big-endian, 0 for little-endian - * po minimal MD padding length - * bs block size (always a power of 2) - * hlen hash output size - */ - - const br_hash_class *dig; - br_hash_compat_context hc; - int be; - uint32_t po, bs; - uint32_t kr, km, kl, kz, u; - uint64_t count, ncount, bit_len; - unsigned char tmp1[64], tmp2[64]; - size_t hlen; - - /* - * Copy the current hash context. - */ - hc = ctx->dig; - - /* - * Get function-specific information. - */ - dig = hc.vtable; - be = (dig->desc & BR_HASHDESC_MD_PADDING_BE) != 0; - po = 9; - if (dig->desc & BR_HASHDESC_MD_PADDING_128) { - po += 8; - } - bs = block_size(dig); - hlen = hash_size(dig); - - /* - * Get current input length and compute total bit length. - */ - count = dig->state(&hc.vtable, tmp1); - bit_len = (count + (uint64_t)len) << 3; - - /* - * We can input the blocks that we are sure we will use. - * This offers better performance (no MUX for these blocks) - * and also ensures that the remaining lengths fit on 32 bits. - */ - ncount = (count + (uint64_t)min_len) & ~(uint64_t)(bs - 1); - if (ncount > count) { - size_t zlen; - - zlen = (size_t)(ncount - count); - dig->update(&hc.vtable, data, zlen); - data = (const unsigned char *)data + zlen; - len -= zlen; - max_len -= zlen; - count = ncount; - } - - /* - * At that point: - * -- 'count' contains the number of bytes already processed - * (in total). - * -- We must input 'len' bytes. 'min_len' is unimportant: we - * used it to know how many full blocks we could process - * directly. Now only len and max_len matter. - * - * We compute kr, kl, kz and km. - * kr number of input bytes already in the current block - * km index of the first byte after the end of the last padding - * block, if length is max_len - * kz index of the last byte of the actual last padding block - * kl index of the start of the encoded length - * - * km, kz and kl are counted from the current offset in the - * input data. - */ - kr = (uint32_t)count & (bs - 1); - kz = ((kr + (uint32_t)len + po + bs - 1) & ~(bs - 1)) - 1 - kr; - kl = kz - 7; - km = ((kr + (uint32_t)max_len + po + bs - 1) & ~(bs - 1)) - kr; - - /* - * We must now process km bytes. For index u from 0 to km-1: - * d is from data[] if u < max_len, 0x00 otherwise - * e is an encoded length byte or 0x00, depending on u - * The tests for d and e need not be constant-time, since - * they relate only to u and max_len, not to the actual length. - * - * Actual input length is then: - * d if u < len - * 0x80 if u == len - * 0x00 if u > len and u < kl - * e if u >= kl - * - * Hash state is obtained whenever we reach a full block. This - * is the result we want if and only if u == kz. - */ - memset(tmp2, 0, sizeof tmp2); - for (u = 0; u < km; u ++) { - uint32_t v; - uint32_t d, e, x0, x1; - unsigned char x[1]; - - d = (u < max_len) ? ((const unsigned char *)data)[u] : 0x00; - v = (kr + u) & (bs - 1); - if (v >= (bs - 8)) { - unsigned j; - - j = (v - (bs - 8)) << 3; - if (be) { - e = (uint32_t)(bit_len >> (56 - j)); - } else { - e = (uint32_t)(bit_len >> j); - } - e &= 0xFF; - } else { - e = 0x00; - } - x0 = MUX(EQ(u, (uint32_t)len), 0x80, d); - x1 = MUX(LT(u, kl), 0x00, e); - x[0] = MUX(LE(u, (uint32_t)len), x0, x1); - dig->update(&hc.vtable, x, 1); - if (v == (bs - 1)) { - dig->state(&hc.vtable, tmp1); - CCOPY(EQ(u, kz), tmp2, tmp1, hlen); - } - } - - /* - * Inner hash output is in tmp2[]; we finish processing. - */ - dig->init(&hc.vtable); - dig->set_state(&hc.vtable, ctx->kso, (uint64_t)bs); - dig->update(&hc.vtable, tmp2, hlen); - dig->out(&hc.vtable, tmp2); - memcpy(out, tmp2, ctx->out_len); - return ctx->out_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/hmac_drbg.c b/src/tls/bearssl/hmac_drbg.c deleted file mode 100644 index 787c96e71..000000000 --- a/src/tls/bearssl/hmac_drbg.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl.h */ -void -br_hmac_drbg_init(br_hmac_drbg_context *ctx, - const br_hash_class *digest_class, const void *seed, size_t len) -{ - size_t hlen; - - ctx->vtable = &br_hmac_drbg_vtable; - hlen = br_digest_size(digest_class); - memset(ctx->K, 0x00, hlen); - memset(ctx->V, 0x01, hlen); - ctx->digest_class = digest_class; - br_hmac_drbg_update(ctx, seed, len); -} - -/* see bearssl.h */ -void -br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len) -{ - const br_hash_class *dig; - br_hmac_key_context kc; - br_hmac_context hc; - size_t hlen; - unsigned char *buf; - unsigned char x; - - dig = ctx->digest_class; - hlen = br_digest_size(dig); - br_hmac_key_init(&kc, dig, ctx->K, hlen); - buf = out; - while (len > 0) { - size_t clen; - - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - br_hmac_out(&hc, ctx->V); - clen = hlen; - if (clen > len) { - clen = len; - } - memcpy(buf, ctx->V, clen); - buf += clen; - len -= clen; - } - - /* - * To prepare the state for the next request, we should call - * br_hmac_drbg_update() with an empty additional seed. However, - * we already have an initialized HMAC context with the right - * initial key, and we don't want to push another one on the - * stack, so we inline that update() call here. - */ - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - x = 0x00; - br_hmac_update(&hc, &x, 1); - br_hmac_out(&hc, ctx->K); - br_hmac_key_init(&kc, dig, ctx->K, hlen); - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - br_hmac_out(&hc, ctx->V); -} - -/* see bearssl.h */ -void -br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t len) -{ - const br_hash_class *dig; - br_hmac_key_context kc; - br_hmac_context hc; - size_t hlen; - unsigned char x; - - dig = ctx->digest_class; - hlen = br_digest_size(dig); - - /* - * 1. K = HMAC(K, V || 0x00 || seed) - */ - br_hmac_key_init(&kc, dig, ctx->K, hlen); - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - x = 0x00; - br_hmac_update(&hc, &x, 1); - br_hmac_update(&hc, seed, len); - br_hmac_out(&hc, ctx->K); - br_hmac_key_init(&kc, dig, ctx->K, hlen); - - /* - * 2. V = HMAC(K, V) - */ - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - br_hmac_out(&hc, ctx->V); - - /* - * 3. If the additional seed is empty, then stop here. - */ - if (len == 0) { - return; - } - - /* - * 4. K = HMAC(K, V || 0x01 || seed) - */ - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - x = 0x01; - br_hmac_update(&hc, &x, 1); - br_hmac_update(&hc, seed, len); - br_hmac_out(&hc, ctx->K); - br_hmac_key_init(&kc, dig, ctx->K, hlen); - - /* - * 5. V = HMAC(K, V) - */ - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, ctx->V, hlen); - br_hmac_out(&hc, ctx->V); -} - -/* see bearssl.h */ -const br_prng_class br_hmac_drbg_vtable = { - sizeof(br_hmac_drbg_context), - (void (*)(const br_prng_class **, const void *, const void *, size_t)) - &br_hmac_drbg_init, - (void (*)(const br_prng_class **, void *, size_t)) - &br_hmac_drbg_generate, - (void (*)(const br_prng_class **, const void *, size_t)) - &br_hmac_drbg_update -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_add.c b/src/tls/bearssl/i15_add.c deleted file mode 100644 index 720cb7348..000000000 --- a/src/tls/bearssl/i15_add.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 31) >> 4; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw + bw + cc; - cc = naw >> 15; - a[u] = MUX(ctl, naw & 0x7FFF, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_bitlen.c b/src/tls/bearssl/i15_bitlen.c deleted file mode 100644 index 7acaafbb5..000000000 --- a/src/tls/bearssl/i15_bitlen.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_bit_length(uint16_t *x, size_t xlen) -{ - uint32_t tw, twk; - - tw = 0; - twk = 0; - while (xlen -- > 0) { - uint32_t w, c; - - c = EQ(tw, 0); - w = x[xlen]; - tw = MUX(c, w, tw); - twk = MUX(c, (uint32_t)xlen, twk); - } - return (twk << 4) + BIT_LENGTH(tw); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_decmod.c b/src/tls/bearssl/i15_decmod.c deleted file mode 100644 index bed19c8a9..000000000 --- a/src/tls/bearssl/i15_decmod.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m) -{ - /* - * Two-pass algorithm: in the first pass, we determine whether the - * value fits; in the second pass, we do the actual write. - * - * During the first pass, 'r' contains the comparison result so - * far: - * 0x00000000 value is equal to the modulus - * 0x00000001 value is greater than the modulus - * 0xFFFFFFFF value is lower than the modulus - * - * Since we iterate starting with the least significant bytes (at - * the end of src[]), each new comparison overrides the previous - * except when the comparison yields 0 (equal). - * - * During the second pass, 'r' is either 0xFFFFFFFF (value fits) - * or 0x00000000 (value does not fit). - * - * We must iterate over all bytes of the source, _and_ possibly - * some extra virtual bytes (with value 0) so as to cover the - * complete modulus as well. We also add 4 such extra bytes beyond - * the modulus length because it then guarantees that no accumulated - * partial word remains to be processed. - */ - const unsigned char *buf; - size_t mlen, tlen; - int pass; - uint32_t r; - - buf = src; - mlen = (m[0] + 15) >> 4; - tlen = (mlen << 1); - if (tlen < len) { - tlen = len; - } - tlen += 4; - r = 0; - for (pass = 0; pass < 2; pass ++) { - size_t u, v; - uint32_t acc; - int acc_len; - - v = 1; - acc = 0; - acc_len = 0; - for (u = 0; u < tlen; u ++) { - uint32_t b; - - if (u < len) { - b = buf[len - 1 - u]; - } else { - b = 0; - } - acc |= (b << acc_len); - acc_len += 8; - if (acc_len >= 15) { - uint32_t xw; - - xw = acc & (uint32_t)0x7FFF; - acc_len -= 15; - acc = b >> (8 - acc_len); - if (v <= mlen) { - if (pass) { - x[v] = r & xw; - } else { - uint32_t cc; - - cc = (uint32_t)CMP(xw, m[v]); - r = MUX(EQ(cc, 0), r, cc); - } - } else { - if (!pass) { - r = MUX(EQ(xw, 0), r, 1); - } - } - v ++; - } - } - - /* - * When we reach this point at the end of the first pass: - * r is either 0, 1 or -1; we want to set r to 0 if it - * is equal to 0 or 1, and leave it to -1 otherwise. - * - * When we reach this point at the end of the second pass: - * r is either 0 or -1; we want to leave that value - * untouched. This is a subcase of the previous. - */ - r >>= 1; - r |= (r << 1); - } - - x[0] = m[0]; - return r & (uint32_t)1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_decode.c b/src/tls/bearssl/i15_decode.c deleted file mode 100644 index 1d0239838..000000000 --- a/src/tls/bearssl/i15_decode.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_decode(uint16_t *x, const void *src, size_t len) -{ - const unsigned char *buf; - size_t v; - uint32_t acc; - int acc_len; - - buf = src; - v = 1; - acc = 0; - acc_len = 0; - while (len -- > 0) { - uint32_t b; - - b = buf[len]; - acc |= (b << acc_len); - acc_len += 8; - if (acc_len >= 15) { - x[v ++] = acc & 0x7FFF; - acc_len -= 15; - acc >>= 15; - } - } - if (acc_len != 0) { - x[v ++] = acc; - } - x[0] = br_i15_bit_length(x + 1, v - 1); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_decred.c b/src/tls/bearssl/i15_decred.c deleted file mode 100644 index 266c93d8e..000000000 --- a/src/tls/bearssl/i15_decred.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_decode_reduce(uint16_t *x, - const void *src, size_t len, const uint16_t *m) -{ - uint32_t m_ebitlen, m_rbitlen; - size_t mblen, k; - const unsigned char *buf; - uint32_t acc; - int acc_len; - - /* - * Get the encoded bit length. - */ - m_ebitlen = m[0]; - - /* - * Special case for an invalid (null) modulus. - */ - if (m_ebitlen == 0) { - x[0] = 0; - return; - } - - /* - * Clear the destination. - */ - br_i15_zero(x, m_ebitlen); - - /* - * First decode directly as many bytes as possible. This requires - * computing the actual bit length. - */ - m_rbitlen = m_ebitlen >> 4; - m_rbitlen = (m_ebitlen & 15) + (m_rbitlen << 4) - m_rbitlen; - mblen = (m_rbitlen + 7) >> 3; - k = mblen - 1; - if (k >= len) { - br_i15_decode(x, src, len); - x[0] = m_ebitlen; - return; - } - buf = src; - br_i15_decode(x, buf, k); - x[0] = m_ebitlen; - - /* - * Input remaining bytes, using 15-bit words. - */ - acc = 0; - acc_len = 0; - while (k < len) { - uint32_t v; - - v = buf[k ++]; - acc = (acc << 8) | v; - acc_len += 8; - if (acc_len >= 15) { - br_i15_muladd_small(x, acc >> (acc_len - 15), m); - acc_len -= 15; - acc &= ~((uint32_t)-1 << acc_len); - } - } - - /* - * We may have some bits accumulated. We then perform a shift to - * be able to inject these bits as a full 15-bit word. - */ - if (acc_len != 0) { - acc = (acc | (x[1] << acc_len)) & 0x7FFF; - br_i15_rshift(x, 15 - acc_len); - br_i15_muladd_small(x, acc, m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_encode.c b/src/tls/bearssl/i15_encode.c deleted file mode 100644 index 262492737..000000000 --- a/src/tls/bearssl/i15_encode.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_encode(void *dst, size_t len, const uint16_t *x) -{ - unsigned char *buf; - size_t u, xlen; - uint32_t acc; - int acc_len; - - xlen = (x[0] + 15) >> 4; - if (xlen == 0) { - memset(dst, 0, len); - return; - } - u = 1; - acc = 0; - acc_len = 0; - buf = dst; - while (len -- > 0) { - if (acc_len < 8) { - if (u <= xlen) { - acc += (uint32_t)x[u ++] << acc_len; - } - acc_len += 15; - } - buf[len] = (unsigned char)acc; - acc >>= 8; - acc_len -= 8; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_fmont.c b/src/tls/bearssl/i15_fmont.c deleted file mode 100644 index 7de8132a0..000000000 --- a/src/tls/bearssl/i15_fmont.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i) -{ - size_t len, u, v; - - len = (m[0] + 15) >> 4; - for (u = 0; u < len; u ++) { - uint32_t f, cc; - - f = MUL15(x[1], m0i) & 0x7FFF; - cc = 0; - for (v = 0; v < len; v ++) { - uint32_t z; - - z = (uint32_t)x[v + 1] + MUL15(f, m[v + 1]) + cc; - cc = z >> 15; - if (v != 0) { - x[v] = z & 0x7FFF; - } - } - x[len] = cc; - } - - /* - * We may have to do an extra subtraction, but only if the - * value in x[] is indeed greater than or equal to that of m[], - * which is why we must do two calls (first call computes the - * carry, second call performs the subtraction only if the carry - * is 0). - */ - br_i15_sub(x, m, NOT(br_i15_sub(x, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_iszero.c b/src/tls/bearssl/i15_iszero.c deleted file mode 100644 index f6cd1b60c..000000000 --- a/src/tls/bearssl/i15_iszero.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_iszero(const uint16_t *x) -{ - uint32_t z; - size_t u; - - z = 0; - for (u = (x[0] + 15) >> 4; u > 0; u --) { - z |= x[u]; - } - return ~(z | -z) >> 31; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_moddiv.c b/src/tls/bearssl/i15_moddiv.c deleted file mode 100644 index 18fdcbd5e..000000000 --- a/src/tls/bearssl/i15_moddiv.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * In this file, we handle big integers with a custom format, i.e. - * without the usual one-word header. Value is split into 15-bit words, - * each stored in a 16-bit slot (top bit is zero) in little-endian - * order. The length (in words) is provided explicitly. In some cases, - * the value can be negative (using two's complement representation). In - * some cases, the top word is allowed to have a 16th bit. - */ - -/* - * Negate big integer conditionally. The value consists of 'len' words, - * with 15 bits in each word (the top bit of each word should be 0, - * except possibly for the last word). If 'ctl' is 1, the negation is - * computed; otherwise, if 'ctl' is 0, then the value is unchanged. - */ -static void -cond_negate(uint16_t *a, size_t len, uint32_t ctl) -{ - size_t k; - uint32_t cc, xm; - - cc = ctl; - xm = 0x7FFF & -ctl; - for (k = 0; k < len; k ++) { - uint32_t aw; - - aw = a[k]; - aw = (aw ^ xm) + cc; - a[k] = aw & 0x7FFF; - cc = (aw >> 15) & 1; - } -} - -/* - * Finish modular reduction. Rules on input parameters: - * - * if neg = 1, then -m <= a < 0 - * if neg = 0, then 0 <= a < 2*m - * - * If neg = 0, then the top word of a[] may use 16 bits. - * - * Also, modulus m must be odd. - */ -static void -finish_mod(uint16_t *a, size_t len, const uint16_t *m, uint32_t neg) -{ - size_t k; - uint32_t cc, xm, ym; - - /* - * First pass: compare a (assumed nonnegative) with m. - */ - cc = 0; - for (k = 0; k < len; k ++) { - uint32_t aw, mw; - - aw = a[k]; - mw = m[k]; - cc = (aw - mw - cc) >> 31; - } - - /* - * At this point: - * if neg = 1, then we must add m (regardless of cc) - * if neg = 0 and cc = 0, then we must subtract m - * if neg = 0 and cc = 1, then we must do nothing - */ - xm = 0x7FFF & -neg; - ym = -(neg | (1 - cc)); - cc = neg; - for (k = 0; k < len; k ++) { - uint32_t aw, mw; - - aw = a[k]; - mw = (m[k] ^ xm) & ym; - aw = aw - mw - cc; - a[k] = aw & 0x7FFF; - cc = aw >> 31; - } -} - -/* - * Compute: - * a <- (a*pa+b*pb)/(2^15) - * b <- (a*qa+b*qb)/(2^15) - * The division is assumed to be exact (i.e. the low word is dropped). - * If the final a is negative, then it is negated. Similarly for b. - * Returned value is the combination of two bits: - * bit 0: 1 if a had to be negated, 0 otherwise - * bit 1: 1 if b had to be negated, 0 otherwise - * - * Factors pa, pb, qa and qb must be at most 2^15 in absolute value. - * Source integers a and b must be nonnegative; top word is not allowed - * to contain an extra 16th bit. - */ -static uint32_t -co_reduce(uint16_t *a, uint16_t *b, size_t len, - int32_t pa, int32_t pb, int32_t qa, int32_t qb) -{ - size_t k; - int32_t cca, ccb; - uint32_t nega, negb; - - cca = 0; - ccb = 0; - for (k = 0; k < len; k ++) { - uint32_t wa, wb, za, zb; - uint16_t tta, ttb; - - /* - * Since: - * |pa| <= 2^15 - * |pb| <= 2^15 - * 0 <= wa <= 2^15 - 1 - * 0 <= wb <= 2^15 - 1 - * |cca| <= 2^16 - 1 - * Then: - * |za| <= (2^15-1)*(2^16) + (2^16-1) = 2^31 - 1 - * - * Thus, the new value of cca is such that |cca| <= 2^16 - 1. - * The same applies to ccb. - */ - wa = a[k]; - wb = b[k]; - za = wa * (uint32_t)pa + wb * (uint32_t)pb + (uint32_t)cca; - zb = wa * (uint32_t)qa + wb * (uint32_t)qb + (uint32_t)ccb; - if (k > 0) { - a[k - 1] = za & 0x7FFF; - b[k - 1] = zb & 0x7FFF; - } - tta = za >> 15; - ttb = zb >> 15; - cca = *(int16_t *)&tta; - ccb = *(int16_t *)&ttb; - } - a[len - 1] = (uint16_t)cca; - b[len - 1] = (uint16_t)ccb; - nega = (uint32_t)cca >> 31; - negb = (uint32_t)ccb >> 31; - cond_negate(a, len, nega); - cond_negate(b, len, negb); - return nega | (negb << 1); -} - -/* - * Compute: - * a <- (a*pa+b*pb)/(2^15) mod m - * b <- (a*qa+b*qb)/(2^15) mod m - * - * m0i is equal to -1/m[0] mod 2^15. - * - * Factors pa, pb, qa and qb must be at most 2^15 in absolute value. - * Source integers a and b must be nonnegative; top word is not allowed - * to contain an extra 16th bit. - */ -static void -co_reduce_mod(uint16_t *a, uint16_t *b, size_t len, - int32_t pa, int32_t pb, int32_t qa, int32_t qb, - const uint16_t *m, uint16_t m0i) -{ - size_t k; - int32_t cca, ccb, fa, fb; - - cca = 0; - ccb = 0; - fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFF; - fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFF; - for (k = 0; k < len; k ++) { - uint32_t wa, wb, za, zb; - uint32_t tta, ttb; - - /* - * In this loop, carries 'cca' and 'ccb' always fit on - * 17 bits (in absolute value). - */ - wa = a[k]; - wb = b[k]; - za = wa * (uint32_t)pa + wb * (uint32_t)pb - + m[k] * (uint32_t)fa + (uint32_t)cca; - zb = wa * (uint32_t)qa + wb * (uint32_t)qb - + m[k] * (uint32_t)fb + (uint32_t)ccb; - if (k > 0) { - a[k - 1] = za & 0x7FFF; - b[k - 1] = zb & 0x7FFF; - } - - /* - * The XOR-and-sub construction below does an arithmetic - * right shift in a portable way (technically, right-shifting - * a negative signed value is implementation-defined in C). - */ -#define M ((uint32_t)1 << 16) - tta = za >> 15; - ttb = zb >> 15; - tta = (tta ^ M) - M; - ttb = (ttb ^ M) - M; - cca = *(int32_t *)&tta; - ccb = *(int32_t *)&ttb; -#undef M - } - a[len - 1] = (uint32_t)cca; - b[len - 1] = (uint32_t)ccb; - - /* - * At this point: - * -m <= a < 2*m - * -m <= b < 2*m - * (this is a case of Montgomery reduction) - * The top word of 'a' and 'b' may have a 16-th bit set. - * We may have to add or subtract the modulus. - */ - finish_mod(a, len, m, (uint32_t)cca >> 31); - finish_mod(b, len, m, (uint32_t)ccb >> 31); -} - -/* see inner.h */ -uint32_t -br_i15_moddiv(uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i, - uint16_t *t) -{ - /* - * Algorithm is an extended binary GCD. We maintain four values - * a, b, u and v, with the following invariants: - * - * a * x = y * u mod m - * b * x = y * v mod m - * - * Starting values are: - * - * a = y - * b = m - * u = x - * v = 0 - * - * The formal definition of the algorithm is a sequence of steps: - * - * - If a is even, then a <- a/2 and u <- u/2 mod m. - * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m. - * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m. - * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m. - * - * Algorithm stops when a = b. At that point, they both are equal - * to GCD(y,m); the modular division succeeds if that value is 1. - * The result of the modular division is then u (or v: both are - * equal at that point). - * - * Each step makes either a or b shrink by at least one bit; hence, - * if m has bit length k bits, then 2k-2 steps are sufficient. - * - * - * Though complexity is quadratic in the size of m, the bit-by-bit - * processing is not very efficient. We can speed up processing by - * remarking that the decisions are taken based only on observation - * of the top and low bits of a and b. - * - * In the loop below, at each iteration, we use the two top words - * of a and b, and the low words of a and b, to compute reduction - * parameters pa, pb, qa and qb such that the new values for a - * and b are: - * - * a' = (a*pa + b*pb) / (2^15) - * b' = (a*qa + b*qb) / (2^15) - * - * the division being exact. - * - * Since the choices are based on the top words, they may be slightly - * off, requiring an optional correction: if a' < 0, then we replace - * pa with -pa, and pb with -pb. The total length of a and b is - * thus reduced by at least 14 bits at each iteration. - * - * The stopping conditions are still the same, though: when a - * and b become equal, they must be both odd (since m is odd, - * the GCD cannot be even), therefore the next operation is a - * subtraction, and one of the values becomes 0. At that point, - * nothing else happens, i.e. one value is stuck at 0, and the - * other one is the GCD. - */ - size_t len, k; - uint16_t *a, *b, *u, *v; - uint32_t num, r; - - len = (m[0] + 15) >> 4; - a = t; - b = a + len; - u = x + 1; - v = b + len; - memcpy(a, y + 1, len * sizeof *y); - memcpy(b, m + 1, len * sizeof *m); - memset(v, 0, len * sizeof *v); - - /* - * Loop below ensures that a and b are reduced by some bits each, - * for a total of at least 14 bits. - */ - for (num = ((m[0] - (m[0] >> 4)) << 1) + 14; num >= 14; num -= 14) { - size_t j; - uint32_t c0, c1; - uint32_t a0, a1, b0, b1; - uint32_t a_hi, b_hi, a_lo, b_lo; - int32_t pa, pb, qa, qb; - int i; - - /* - * Extract top words of a and b. If j is the highest - * index >= 1 such that a[j] != 0 or b[j] != 0, then we want - * (a[j] << 15) + a[j - 1], and (b[j] << 15) + b[j - 1]. - * If a and b are down to one word each, then we use a[0] - * and b[0]. - */ - c0 = (uint32_t)-1; - c1 = (uint32_t)-1; - a0 = 0; - a1 = 0; - b0 = 0; - b1 = 0; - j = len; - while (j -- > 0) { - uint32_t aw, bw; - - aw = a[j]; - bw = b[j]; - a0 ^= (a0 ^ aw) & c0; - a1 ^= (a1 ^ aw) & c1; - b0 ^= (b0 ^ bw) & c0; - b1 ^= (b1 ^ bw) & c1; - c1 = c0; - c0 &= (((aw | bw) + 0xFFFF) >> 16) - (uint32_t)1; - } - - /* - * If c1 = 0, then we grabbed two words for a and b. - * If c1 != 0 but c0 = 0, then we grabbed one word. It - * is not possible that c1 != 0 and c0 != 0, because that - * would mean that both integers are zero. - */ - a1 |= a0 & c1; - a0 &= ~c1; - b1 |= b0 & c1; - b0 &= ~c1; - a_hi = (a0 << 15) + a1; - b_hi = (b0 << 15) + b1; - a_lo = a[0]; - b_lo = b[0]; - - /* - * Compute reduction factors: - * - * a' = a*pa + b*pb - * b' = a*qa + b*qb - * - * such that a' and b' are both multiple of 2^15, but are - * only marginally larger than a and b. - */ - pa = 1; - pb = 0; - qa = 0; - qb = 1; - for (i = 0; i < 15; i ++) { - /* - * At each iteration: - * - * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi - * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi - * a <- a/2 if: a is even - * b <- b/2 if: a is odd, b is even - * - * We multiply a_lo and b_lo by 2 at each - * iteration, thus a division by 2 really is a - * non-multiplication by 2. - */ - uint32_t r, oa, ob, cAB, cBA, cA; - - /* - * cAB = 1 if b must be subtracted from a - * cBA = 1 if a must be subtracted from b - * cA = 1 if a is divided by 2, 0 otherwise - * - * Rules: - * - * cAB and cBA cannot be both 1. - * if a is not divided by 2, b is. - */ - r = GT(a_hi, b_hi); - oa = (a_lo >> i) & 1; - ob = (b_lo >> i) & 1; - cAB = oa & ob & r; - cBA = oa & ob & NOT(r); - cA = cAB | NOT(oa); - - /* - * Conditional subtractions. - */ - a_lo -= b_lo & -cAB; - a_hi -= b_hi & -cAB; - pa -= qa & -(int32_t)cAB; - pb -= qb & -(int32_t)cAB; - b_lo -= a_lo & -cBA; - b_hi -= a_hi & -cBA; - qa -= pa & -(int32_t)cBA; - qb -= pb & -(int32_t)cBA; - - /* - * Shifting. - */ - a_lo += a_lo & (cA - 1); - pa += pa & ((int32_t)cA - 1); - pb += pb & ((int32_t)cA - 1); - a_hi ^= (a_hi ^ (a_hi >> 1)) & -cA; - b_lo += b_lo & -cA; - qa += qa & -(int32_t)cA; - qb += qb & -(int32_t)cA; - b_hi ^= (b_hi ^ (b_hi >> 1)) & (cA - 1); - } - - /* - * Replace a and b with new values a' and b'. - */ - r = co_reduce(a, b, len, pa, pb, qa, qb); - pa -= pa * ((r & 1) << 1); - pb -= pb * ((r & 1) << 1); - qa -= qa * (r & 2); - qb -= qb * (r & 2); - co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i); - } - - /* - * Now one of the arrays should be 0, and the other contains - * the GCD. If a is 0, then u is 0 as well, and v contains - * the division result. - * Result is correct if and only if GCD is 1. - */ - r = (a[0] | b[0]) ^ 1; - u[0] |= v[0]; - for (k = 1; k < len; k ++) { - r |= a[k] | b[k]; - u[k] |= v[k]; - } - return EQ0(r); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_modpow.c b/src/tls/bearssl/i15_modpow.c deleted file mode 100644 index 14d694968..000000000 --- a/src/tls/bearssl/i15_modpow.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_modpow(uint16_t *x, - const unsigned char *e, size_t elen, - const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2) -{ - size_t mlen; - unsigned k; - - mlen = ((m[0] + 31) >> 4) * sizeof m[0]; - memcpy(t1, x, mlen); - br_i15_to_monty(t1, m); - br_i15_zero(x, m[0]); - x[1] = 1; - for (k = 0; k < ((unsigned)elen << 3); k ++) { - uint32_t ctl; - - ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; - br_i15_montymul(t2, x, t1, m, m0i); - CCOPY(ctl, x, t2, mlen); - br_i15_montymul(t2, t1, t1, m, m0i); - memcpy(t1, t2, mlen); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_modpow2.c b/src/tls/bearssl/i15_modpow2.c deleted file mode 100644 index d10817830..000000000 --- a/src/tls/bearssl/i15_modpow2.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_modpow_opt(uint16_t *x, - const unsigned char *e, size_t elen, - const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen) -{ - size_t mlen, mwlen; - uint16_t *t1, *t2, *base; - size_t u, v; - uint32_t acc; - int acc_len, win_len; - - /* - * Get modulus size. - */ - mwlen = (m[0] + 31) >> 4; - mlen = mwlen * sizeof m[0]; - mwlen += (mwlen & 1); - t1 = tmp; - t2 = tmp + mwlen; - - /* - * Compute possible window size, with a maximum of 5 bits. - * When the window has size 1 bit, we use a specific code - * that requires only two temporaries. Otherwise, for a - * window of k bits, we need 2^k+1 temporaries. - */ - if (twlen < (mwlen << 1)) { - return 0; - } - for (win_len = 5; win_len > 1; win_len --) { - if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) { - break; - } - } - - /* - * Everything is done in Montgomery representation. - */ - br_i15_to_monty(x, m); - - /* - * Compute window contents. If the window has size one bit only, - * then t2 is set to x; otherwise, t2[0] is left untouched, and - * t2[k] is set to x^k (for k >= 1). - */ - if (win_len == 1) { - memcpy(t2, x, mlen); - } else { - memcpy(t2 + mwlen, x, mlen); - base = t2 + mwlen; - for (u = 2; u < ((unsigned)1 << win_len); u ++) { - br_i15_montymul(base + mwlen, base, x, m, m0i); - base += mwlen; - } - } - - /* - * We need to set x to 1, in Montgomery representation. This can - * be done efficiently by setting the high word to 1, then doing - * one word-sized shift. - */ - br_i15_zero(x, m[0]); - x[(m[0] + 15) >> 4] = 1; - br_i15_muladd_small(x, 0, m); - - /* - * We process bits from most to least significant. At each - * loop iteration, we have acc_len bits in acc. - */ - acc = 0; - acc_len = 0; - while (acc_len > 0 || elen > 0) { - int i, k; - uint32_t bits; - - /* - * Get the next bits. - */ - k = win_len; - if (acc_len < win_len) { - if (elen > 0) { - acc = (acc << 8) | *e ++; - elen --; - acc_len += 8; - } else { - k = acc_len; - } - } - bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); - acc_len -= k; - - /* - * We could get exactly k bits. Compute k squarings. - */ - for (i = 0; i < k; i ++) { - br_i15_montymul(t1, x, x, m, m0i); - memcpy(x, t1, mlen); - } - - /* - * Window lookup: we want to set t2 to the window - * lookup value, assuming the bits are non-zero. If - * the window length is 1 bit only, then t2 is - * already set; otherwise, we do a constant-time lookup. - */ - if (win_len > 1) { - br_i15_zero(t2, m[0]); - base = t2 + mwlen; - for (u = 1; u < ((uint32_t)1 << k); u ++) { - uint32_t mask; - - mask = -EQ(u, bits); - for (v = 1; v < mwlen; v ++) { - t2[v] |= mask & base[v]; - } - base += mwlen; - } - } - - /* - * Multiply with the looked-up value. We keep the - * product only if the exponent bits are not all-zero. - */ - br_i15_montymul(t1, x, t2, m, m0i); - CCOPY(NEQ(bits, 0), x, t1, mlen); - } - - /* - * Convert back from Montgomery representation, and exit. - */ - br_i15_from_monty(x, m, m0i); - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_montmul.c b/src/tls/bearssl/i15_montmul.c deleted file mode 100644 index e7313ae80..000000000 --- a/src/tls/bearssl/i15_montmul.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, - const uint16_t *m, uint16_t m0i) -{ - size_t len, len4, u, v; - uint32_t dh; - - len = (m[0] + 15) >> 4; - len4 = len & ~(size_t)3; - br_i15_zero(d, m[0]); - dh = 0; - for (u = 0; u < len; u ++) { - uint32_t f, xu, r, zh; - - xu = x[u + 1]; - f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i) - & 0x7FFF; -#if BR_ARMEL_CORTEXM_GCC - if (len4 != 0) { - uint16_t *limit; - - limit = d + len4; - asm volatile ( -"\n\ - @ carry: r=r2 \n\ - @ multipliers: xu=r3 f=r4 \n\ - @ base registers: d+v=r5 y+v=r6 m+v=r7 \n\ - @ r8 contains 0x7FFF \n\ - @ r9 contains d+len4 \n\ - ldr r0, %[limit] \n\ - ldr r3, %[xu] \n\ - mov r9, r0 \n\ - ldr r4, %[f] \n\ - eor r2, r2 \n\ - ldr r5, %[d] \n\ - sub r1, r2, #1 \n\ - ldr r6, %[y] \n\ - lsr r1, r1, #17 \n\ - ldr r7, %[m] \n\ - mov r8, r1 \n\ -loop%=: \n\ - ldrh r0, [r6, #2] \n\ - ldrh r1, [r7, #2] \n\ - mul r0, r3 \n\ - mul r1, r4 \n\ - add r2, r0, r2 \n\ - ldrh r0, [r5, #2] \n\ - add r2, r1, r2 \n\ - mov r1, r8 \n\ - add r2, r0, r2 \n\ - and r1, r2 \n\ - lsr r2, r2, #15 \n\ - strh r1, [r5, #0] \n\ - \n\ - ldrh r0, [r6, #4] \n\ - ldrh r1, [r7, #4] \n\ - mul r0, r3 \n\ - mul r1, r4 \n\ - add r2, r0, r2 \n\ - ldrh r0, [r5, #4] \n\ - add r2, r1, r2 \n\ - mov r1, r8 \n\ - add r2, r0, r2 \n\ - and r1, r2 \n\ - lsr r2, r2, #15 \n\ - strh r1, [r5, #2] \n\ - \n\ - ldrh r0, [r6, #6] \n\ - ldrh r1, [r7, #6] \n\ - mul r0, r3 \n\ - mul r1, r4 \n\ - add r2, r0, r2 \n\ - ldrh r0, [r5, #6] \n\ - add r2, r1, r2 \n\ - mov r1, r8 \n\ - add r2, r0, r2 \n\ - and r1, r2 \n\ - lsr r2, r2, #15 \n\ - strh r1, [r5, #4] \n\ - \n\ - ldrh r0, [r6, #8] \n\ - ldrh r1, [r7, #8] \n\ - mul r0, r3 \n\ - mul r1, r4 \n\ - add r2, r0, r2 \n\ - ldrh r0, [r5, #8] \n\ - add r2, r1, r2 \n\ - mov r1, r8 \n\ - add r2, r0, r2 \n\ - and r1, r2 \n\ - lsr r2, r2, #15 \n\ - strh r1, [r5, #6] \n\ - \n\ - add r5, r5, #8 \n\ - add r6, r6, #8 \n\ - add r7, r7, #8 \n\ - cmp r5, r9 \n\ - bne loop%= \n\ - \n\ - str r2, %[carry] \n\ -" -: [carry] "=m" (r) -: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y), - [m] "m" (m), [limit] "m" (limit) -: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - } else { - r = 0; - } - v = len4; -#else - r = 0; - for (v = 0; v < len4; v += 4) { - uint32_t z; - - z = d[v + 1] + MUL15(xu, y[v + 1]) - + MUL15(f, m[v + 1]) + r; - r = z >> 15; - d[v + 0] = z & 0x7FFF; - z = d[v + 2] + MUL15(xu, y[v + 2]) - + MUL15(f, m[v + 2]) + r; - r = z >> 15; - d[v + 1] = z & 0x7FFF; - z = d[v + 3] + MUL15(xu, y[v + 3]) - + MUL15(f, m[v + 3]) + r; - r = z >> 15; - d[v + 2] = z & 0x7FFF; - z = d[v + 4] + MUL15(xu, y[v + 4]) - + MUL15(f, m[v + 4]) + r; - r = z >> 15; - d[v + 3] = z & 0x7FFF; - } -#endif - for (; v < len; v ++) { - uint32_t z; - - z = d[v + 1] + MUL15(xu, y[v + 1]) - + MUL15(f, m[v + 1]) + r; - r = z >> 15; - d[v + 0] = z & 0x7FFF; - } - - zh = dh + r; - d[len] = zh & 0x7FFF; - dh = zh >> 15; - } - - /* - * Restore the bit length (it was overwritten in the loop above). - */ - d[0] = m[0]; - - /* - * d[] may be greater than m[], but it is still lower than twice - * the modulus. - */ - br_i15_sub(d, m, NEQ(dh, 0) | NOT(br_i15_sub(d, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_mulacc.c b/src/tls/bearssl/i15_mulacc.c deleted file mode 100644 index 9a48a180c..000000000 --- a/src/tls/bearssl/i15_mulacc.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b) -{ - size_t alen, blen, u; - unsigned dl, dh; - - alen = (a[0] + 15) >> 4; - blen = (b[0] + 15) >> 4; - - /* - * Announced bit length of d[] will be the sum of the announced - * bit lengths of a[] and b[]; but the lengths are encoded. - */ - dl = (a[0] & 15) + (b[0] & 15); - dh = (a[0] >> 4) + (b[0] >> 4); - d[0] = (dh << 4) + dl + (~(uint32_t)(dl - 15) >> 31); - - for (u = 0; u < blen; u ++) { - uint32_t f; - size_t v; - uint32_t cc; - - f = b[1 + u]; - cc = 0; - for (v = 0; v < alen; v ++) { - uint32_t z; - - z = (uint32_t)d[1 + u + v] + MUL15(f, a[1 + v]) + cc; - cc = z >> 15; - d[1 + u + v] = z & 0x7FFF; - } - d[1 + u + alen] = cc; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_muladd.c b/src/tls/bearssl/i15_muladd.c deleted file mode 100644 index 4c68cf73a..000000000 --- a/src/tls/bearssl/i15_muladd.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Constant-time division. The divisor must not be larger than 16 bits, - * and the quotient must fit on 17 bits. - */ -static uint32_t -divrem16(uint32_t x, uint32_t d, uint32_t *r) -{ - int i; - uint32_t q; - - q = 0; - d <<= 16; - for (i = 16; i >= 0; i --) { - uint32_t ctl; - - ctl = LE(d, x); - q |= ctl << i; - x -= (-ctl) & d; - d >>= 1; - } - if (r != NULL) { - *r = x; - } - return q; -} - -/* see inner.h */ -void -br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m) -{ - /* - * Constant-time: we accept to leak the exact bit length of the - * modulus m. - */ - unsigned m_bitlen, mblr; - size_t u, mlen; - uint32_t hi, a0, a, b, q; - uint32_t cc, tb, over, under; - - /* - * Simple case: the modulus fits on one word. - */ - m_bitlen = m[0]; - if (m_bitlen == 0) { - return; - } - if (m_bitlen <= 15) { - uint32_t rem; - - divrem16(((uint32_t)x[1] << 15) | z, m[1], &rem); - x[1] = rem; - return; - } - mlen = (m_bitlen + 15) >> 4; - mblr = m_bitlen & 15; - - /* - * Principle: we estimate the quotient (x*2^15+z)/m by - * doing a 30/15 division with the high words. - * - * Let: - * w = 2^15 - * a = (w*a0 + a1) * w^N + a2 - * b = b0 * w^N + b2 - * such that: - * 0 <= a0 < w - * 0 <= a1 < w - * 0 <= a2 < w^N - * w/2 <= b0 < w - * 0 <= b2 < w^N - * a < w*b - * I.e. the two top words of a are a0:a1, the top word of b is - * b0, we ensured that b0 is "full" (high bit set), and a is - * such that the quotient q = a/b fits on one word (0 <= q < w). - * - * If a = b*q + r (with 0 <= r < q), then we can estimate q by - * using a division on the top words: - * a0*w + a1 = b0*u + v (with 0 <= v < b0) - * Then the following holds: - * 0 <= u <= w - * u-2 <= q <= u - */ - hi = x[mlen]; - if (mblr == 0) { - a0 = x[mlen]; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); - x[1] = z; - a = (a0 << 15) + x[mlen]; - b = m[mlen]; - } else { - a0 = (x[mlen] << (15 - mblr)) | (x[mlen - 1] >> mblr); - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); - x[1] = z; - a = (a0 << 15) | (((x[mlen] << (15 - mblr)) - | (x[mlen - 1] >> mblr)) & 0x7FFF); - b = (m[mlen] << (15 - mblr)) | (m[mlen - 1] >> mblr); - } - q = divrem16(a, b, NULL); - - /* - * We computed an estimate for q, but the real one may be q, - * q-1 or q-2; moreover, the division may have returned a value - * 8000 or even 8001 if the two high words were identical, and - * we want to avoid values beyond 7FFF. We thus adjust q so - * that the "true" multiplier will be q+1, q or q-1, and q is - * in the 0000..7FFF range. - */ - q = MUX(EQ(b, a0), 0x7FFF, q - 1 + ((q - 1) >> 31)); - - /* - * We subtract q*m from x (x has an extra high word of value 'hi'). - * Since q may be off by 1 (in either direction), we may have to - * add or subtract m afterwards. - * - * The 'tb' flag will be true (1) at the end of the loop if the - * result is greater than or equal to the modulus (not counting - * 'hi' or the carry). - */ - cc = 0; - tb = 1; - for (u = 1; u <= mlen; u ++) { - uint32_t mw, zl, xw, nxw; - - mw = m[u]; - zl = MUL15(mw, q) + cc; - cc = zl >> 15; - zl &= 0x7FFF; - xw = x[u]; - nxw = xw - zl; - cc += nxw >> 31; - nxw &= 0x7FFF; - x[u] = nxw; - tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); - } - - /* - * If we underestimated q, then either cc < hi (one extra bit - * beyond the top array word), or cc == hi and tb is true (no - * extra bit, but the result is not lower than the modulus). - * - * If we overestimated q, then cc > hi. - */ - over = GT(cc, hi); - under = ~over & (tb | LT(cc, hi)); - br_i15_add(x, m, over); - br_i15_sub(x, m, under); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_ninv15.c b/src/tls/bearssl/i15_ninv15.c deleted file mode 100644 index 6c178ee79..000000000 --- a/src/tls/bearssl/i15_ninv15.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint16_t -br_i15_ninv15(uint16_t x) -{ - uint32_t y; - - y = 2 - x; - y = MUL15(y, 2 - MUL15(x, y)); - y = MUL15(y, 2 - MUL15(x, y)); - y = MUL15(y, 2 - MUL15(x, y)); - return MUX(x & 1, -y, 0) & 0x7FFF; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_reduce.c b/src/tls/bearssl/i15_reduce.c deleted file mode 100644 index 87c1cb7a2..000000000 --- a/src/tls/bearssl/i15_reduce.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m) -{ - uint32_t m_bitlen, a_bitlen; - size_t mlen, alen, u; - - m_bitlen = m[0]; - mlen = (m_bitlen + 15) >> 4; - - x[0] = m_bitlen; - if (m_bitlen == 0) { - return; - } - - /* - * If the source is shorter, then simply copy all words from a[] - * and zero out the upper words. - */ - a_bitlen = a[0]; - alen = (a_bitlen + 15) >> 4; - if (a_bitlen < m_bitlen) { - memcpy(x + 1, a + 1, alen * sizeof *a); - for (u = alen; u < mlen; u ++) { - x[u + 1] = 0; - } - return; - } - - /* - * The source length is at least equal to that of the modulus. - * We must thus copy N-1 words, and input the remaining words - * one by one. - */ - memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); - x[mlen] = 0; - for (u = 1 + alen - mlen; u > 0; u --) { - br_i15_muladd_small(x, a[u], m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_rshift.c b/src/tls/bearssl/i15_rshift.c deleted file mode 100644 index 2240ce63c..000000000 --- a/src/tls/bearssl/i15_rshift.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_rshift(uint16_t *x, int count) -{ - size_t u, len; - unsigned r; - - len = (x[0] + 15) >> 4; - if (len == 0) { - return; - } - r = x[1] >> count; - for (u = 2; u <= len; u ++) { - unsigned w; - - w = x[u]; - x[u - 1] = ((w << (15 - count)) | r) & 0x7FFF; - r = w >> count; - } - x[len] = r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_sub.c b/src/tls/bearssl/i15_sub.c deleted file mode 100644 index 1270c3b02..000000000 --- a/src/tls/bearssl/i15_sub.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 31) >> 4; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw - bw - cc; - cc = naw >> 31; - a[u] = MUX(ctl, naw & 0x7FFF, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i15_tmont.c b/src/tls/bearssl/i15_tmont.c deleted file mode 100644 index e182b9e21..000000000 --- a/src/tls/bearssl/i15_tmont.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i15_to_monty(uint16_t *x, const uint16_t *m) -{ - unsigned k; - - for (k = (m[0] + 15) >> 4; k > 0; k --) { - br_i15_muladd_small(x, 0, m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_add.c b/src/tls/bearssl/i31_add.c deleted file mode 100644 index d66e948a7..000000000 --- a/src/tls/bearssl/i31_add.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 63) >> 5; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw + bw + cc; - cc = naw >> 31; - a[u] = MUX(ctl, naw & (uint32_t)0x7FFFFFFF, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_bitlen.c b/src/tls/bearssl/i31_bitlen.c deleted file mode 100644 index 2bfb0e3fc..000000000 --- a/src/tls/bearssl/i31_bitlen.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_bit_length(uint32_t *x, size_t xlen) -{ - uint32_t tw, twk; - - tw = 0; - twk = 0; - while (xlen -- > 0) { - uint32_t w, c; - - c = EQ(tw, 0); - w = x[xlen]; - tw = MUX(c, w, tw); - twk = MUX(c, (uint32_t)xlen, twk); - } - return (twk << 5) + BIT_LENGTH(tw); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_decmod.c b/src/tls/bearssl/i31_decmod.c deleted file mode 100644 index 9b085e964..000000000 --- a/src/tls/bearssl/i31_decmod.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m) -{ - /* - * Two-pass algorithm: in the first pass, we determine whether the - * value fits; in the second pass, we do the actual write. - * - * During the first pass, 'r' contains the comparison result so - * far: - * 0x00000000 value is equal to the modulus - * 0x00000001 value is greater than the modulus - * 0xFFFFFFFF value is lower than the modulus - * - * Since we iterate starting with the least significant bytes (at - * the end of src[]), each new comparison overrides the previous - * except when the comparison yields 0 (equal). - * - * During the second pass, 'r' is either 0xFFFFFFFF (value fits) - * or 0x00000000 (value does not fit). - * - * We must iterate over all bytes of the source, _and_ possibly - * some extra virtual bytes (with value 0) so as to cover the - * complete modulus as well. We also add 4 such extra bytes beyond - * the modulus length because it then guarantees that no accumulated - * partial word remains to be processed. - */ - const unsigned char *buf; - size_t mlen, tlen; - int pass; - uint32_t r; - - buf = src; - mlen = (m[0] + 31) >> 5; - tlen = (mlen << 2); - if (tlen < len) { - tlen = len; - } - tlen += 4; - r = 0; - for (pass = 0; pass < 2; pass ++) { - size_t u, v; - uint32_t acc; - int acc_len; - - v = 1; - acc = 0; - acc_len = 0; - for (u = 0; u < tlen; u ++) { - uint32_t b; - - if (u < len) { - b = buf[len - 1 - u]; - } else { - b = 0; - } - acc |= (b << acc_len); - acc_len += 8; - if (acc_len >= 31) { - uint32_t xw; - - xw = acc & (uint32_t)0x7FFFFFFF; - acc_len -= 31; - acc = b >> (8 - acc_len); - if (v <= mlen) { - if (pass) { - x[v] = r & xw; - } else { - uint32_t cc; - - cc = (uint32_t)CMP(xw, m[v]); - r = MUX(EQ(cc, 0), r, cc); - } - } else { - if (!pass) { - r = MUX(EQ(xw, 0), r, 1); - } - } - v ++; - } - } - - /* - * When we reach this point at the end of the first pass: - * r is either 0, 1 or -1; we want to set r to 0 if it - * is equal to 0 or 1, and leave it to -1 otherwise. - * - * When we reach this point at the end of the second pass: - * r is either 0 or -1; we want to leave that value - * untouched. This is a subcase of the previous. - */ - r >>= 1; - r |= (r << 1); - } - - x[0] = m[0]; - return r & (uint32_t)1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_decode.c b/src/tls/bearssl/i31_decode.c deleted file mode 100644 index ef142ba20..000000000 --- a/src/tls/bearssl/i31_decode.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_decode(uint32_t *x, const void *src, size_t len) -{ - const unsigned char *buf; - size_t u, v; - uint32_t acc; - int acc_len; - - buf = src; - u = len; - v = 1; - acc = 0; - acc_len = 0; - while (u -- > 0) { - uint32_t b; - - b = buf[u]; - acc |= (b << acc_len); - acc_len += 8; - if (acc_len >= 31) { - x[v ++] = acc & (uint32_t)0x7FFFFFFF; - acc_len -= 31; - acc = b >> (8 - acc_len); - } - } - if (acc_len != 0) { - x[v ++] = acc; - } - x[0] = br_i31_bit_length(x + 1, v - 1); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_decred.c b/src/tls/bearssl/i31_decred.c deleted file mode 100644 index 429b7f1d0..000000000 --- a/src/tls/bearssl/i31_decred.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_decode_reduce(uint32_t *x, - const void *src, size_t len, const uint32_t *m) -{ - uint32_t m_ebitlen, m_rbitlen; - size_t mblen, k; - const unsigned char *buf; - uint32_t acc; - int acc_len; - - /* - * Get the encoded bit length. - */ - m_ebitlen = m[0]; - - /* - * Special case for an invalid (null) modulus. - */ - if (m_ebitlen == 0) { - x[0] = 0; - return; - } - - /* - * Clear the destination. - */ - br_i31_zero(x, m_ebitlen); - - /* - * First decode directly as many bytes as possible. This requires - * computing the actual bit length. - */ - m_rbitlen = m_ebitlen >> 5; - m_rbitlen = (m_ebitlen & 31) + (m_rbitlen << 5) - m_rbitlen; - mblen = (m_rbitlen + 7) >> 3; - k = mblen - 1; - if (k >= len) { - br_i31_decode(x, src, len); - x[0] = m_ebitlen; - return; - } - buf = src; - br_i31_decode(x, buf, k); - x[0] = m_ebitlen; - - /* - * Input remaining bytes, using 31-bit words. - */ - acc = 0; - acc_len = 0; - while (k < len) { - uint32_t v; - - v = buf[k ++]; - if (acc_len >= 23) { - acc_len -= 23; - acc <<= (8 - acc_len); - acc |= v >> acc_len; - br_i31_muladd_small(x, acc, m); - acc = v & (0xFF >> (8 - acc_len)); - } else { - acc = (acc << 8) | v; - acc_len += 8; - } - } - - /* - * We may have some bits accumulated. We then perform a shift to - * be able to inject these bits as a full 31-bit word. - */ - if (acc_len != 0) { - acc = (acc | (x[1] << acc_len)) & 0x7FFFFFFF; - br_i31_rshift(x, 31 - acc_len); - br_i31_muladd_small(x, acc, m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_encode.c b/src/tls/bearssl/i31_encode.c deleted file mode 100644 index 79966df8a..000000000 --- a/src/tls/bearssl/i31_encode.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_encode(void *dst, size_t len, const uint32_t *x) -{ - unsigned char *buf; - size_t k, xlen; - uint32_t acc; - int acc_len; - - xlen = (x[0] + 31) >> 5; - if (xlen == 0) { - memset(dst, 0, len); - return; - } - buf = (unsigned char *)dst + len; - k = 1; - acc = 0; - acc_len = 0; - while (len != 0) { - uint32_t w; - - w = (k <= xlen) ? x[k] : 0; - k ++; - if (acc_len == 0) { - acc = w; - acc_len = 31; - } else { - uint32_t z; - - z = acc | (w << acc_len); - acc_len --; - acc = w >> (31 - acc_len); - if (len >= 4) { - buf -= 4; - len -= 4; - br_enc32be(buf, z); - } else { - switch (len) { - case 3: - buf[-3] = (unsigned char)(z >> 16); - /* fall through */ - case 2: - buf[-2] = (unsigned char)(z >> 8); - /* fall through */ - case 1: - buf[-1] = (unsigned char)z; - break; - } - return; - } - } - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_fmont.c b/src/tls/bearssl/i31_fmont.c deleted file mode 100644 index 63d2de431..000000000 --- a/src/tls/bearssl/i31_fmont.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i) -{ - size_t len, u, v; - - len = (m[0] + 31) >> 5; - for (u = 0; u < len; u ++) { - uint32_t f; - uint64_t cc; - - f = MUL31_lo(x[1], m0i); - cc = 0; - for (v = 0; v < len; v ++) { - uint64_t z; - - z = (uint64_t)x[v + 1] + MUL31(f, m[v + 1]) + cc; - cc = z >> 31; - if (v != 0) { - x[v] = (uint32_t)z & 0x7FFFFFFF; - } - } - x[len] = (uint32_t)cc; - } - - /* - * We may have to do an extra subtraction, but only if the - * value in x[] is indeed greater than or equal to that of m[], - * which is why we must do two calls (first call computes the - * carry, second call performs the subtraction only if the carry - * is 0). - */ - br_i31_sub(x, m, NOT(br_i31_sub(x, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_iszero.c b/src/tls/bearssl/i31_iszero.c deleted file mode 100644 index 08eeacb1d..000000000 --- a/src/tls/bearssl/i31_iszero.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_iszero(const uint32_t *x) -{ - uint32_t z; - size_t u; - - z = 0; - for (u = (x[0] + 31) >> 5; u > 0; u --) { - z |= x[u]; - } - return ~(z | -z) >> 31; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_moddiv.c b/src/tls/bearssl/i31_moddiv.c deleted file mode 100644 index 13474f569..000000000 --- a/src/tls/bearssl/i31_moddiv.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * In this file, we handle big integers with a custom format, i.e. - * without the usual one-word header. Value is split into 31-bit words, - * each stored in a 32-bit slot (top bit is zero) in little-endian - * order. The length (in words) is provided explicitly. In some cases, - * the value can be negative (using two's complement representation). In - * some cases, the top word is allowed to have a 32th bit. - */ - -/* - * Negate big integer conditionally. The value consists of 'len' words, - * with 31 bits in each word (the top bit of each word should be 0, - * except possibly for the last word). If 'ctl' is 1, the negation is - * computed; otherwise, if 'ctl' is 0, then the value is unchanged. - */ -static void -cond_negate(uint32_t *a, size_t len, uint32_t ctl) -{ - size_t k; - uint32_t cc, xm; - - cc = ctl; - xm = -ctl >> 1; - for (k = 0; k < len; k ++) { - uint32_t aw; - - aw = a[k]; - aw = (aw ^ xm) + cc; - a[k] = aw & 0x7FFFFFFF; - cc = aw >> 31; - } -} - -/* - * Finish modular reduction. Rules on input parameters: - * - * if neg = 1, then -m <= a < 0 - * if neg = 0, then 0 <= a < 2*m - * - * If neg = 0, then the top word of a[] may use 32 bits. - * - * Also, modulus m must be odd. - */ -static void -finish_mod(uint32_t *a, size_t len, const uint32_t *m, uint32_t neg) -{ - size_t k; - uint32_t cc, xm, ym; - - /* - * First pass: compare a (assumed nonnegative) with m. - * Note that if the final word uses the top extra bit, then - * subtracting m must yield a value less than 2^31, since we - * assumed that a < 2*m. - */ - cc = 0; - for (k = 0; k < len; k ++) { - uint32_t aw, mw; - - aw = a[k]; - mw = m[k]; - cc = (aw - mw - cc) >> 31; - } - - /* - * At this point: - * if neg = 1, then we must add m (regardless of cc) - * if neg = 0 and cc = 0, then we must subtract m - * if neg = 0 and cc = 1, then we must do nothing - */ - xm = -neg >> 1; - ym = -(neg | (1 - cc)); - cc = neg; - for (k = 0; k < len; k ++) { - uint32_t aw, mw; - - aw = a[k]; - mw = (m[k] ^ xm) & ym; - aw = aw - mw - cc; - a[k] = aw & 0x7FFFFFFF; - cc = aw >> 31; - } -} - -/* - * Compute: - * a <- (a*pa+b*pb)/(2^31) - * b <- (a*qa+b*qb)/(2^31) - * The division is assumed to be exact (i.e. the low word is dropped). - * If the final a is negative, then it is negated. Similarly for b. - * Returned value is the combination of two bits: - * bit 0: 1 if a had to be negated, 0 otherwise - * bit 1: 1 if b had to be negated, 0 otherwise - * - * Factors pa, pb, qa and qb must be at most 2^31 in absolute value. - * Source integers a and b must be nonnegative; top word is not allowed - * to contain an extra 32th bit. - */ -static uint32_t -co_reduce(uint32_t *a, uint32_t *b, size_t len, - int64_t pa, int64_t pb, int64_t qa, int64_t qb) -{ - size_t k; - int64_t cca, ccb; - uint32_t nega, negb; - - cca = 0; - ccb = 0; - for (k = 0; k < len; k ++) { - uint32_t wa, wb; - uint64_t za, zb; - uint64_t tta, ttb; - - /* - * Since: - * |pa| <= 2^31 - * |pb| <= 2^31 - * 0 <= wa <= 2^31 - 1 - * 0 <= wb <= 2^31 - 1 - * |cca| <= 2^32 - 1 - * Then: - * |za| <= (2^31-1)*(2^32) + (2^32-1) = 2^63 - 1 - * - * Thus, the new value of cca is such that |cca| <= 2^32 - 1. - * The same applies to ccb. - */ - wa = a[k]; - wb = b[k]; - za = wa * (uint64_t)pa + wb * (uint64_t)pb + (uint64_t)cca; - zb = wa * (uint64_t)qa + wb * (uint64_t)qb + (uint64_t)ccb; - if (k > 0) { - a[k - 1] = za & 0x7FFFFFFF; - b[k - 1] = zb & 0x7FFFFFFF; - } - - /* - * For the new values of cca and ccb, we need a signed - * right-shift; since, in C, right-shifting a signed - * negative value is implementation-defined, we use a - * custom portable sign extension expression. - */ -#define M ((uint64_t)1 << 32) - tta = za >> 31; - ttb = zb >> 31; - tta = (tta ^ M) - M; - ttb = (ttb ^ M) - M; - cca = *(int64_t *)&tta; - ccb = *(int64_t *)&ttb; -#undef M - } - a[len - 1] = (uint32_t)cca; - b[len - 1] = (uint32_t)ccb; - - nega = (uint32_t)((uint64_t)cca >> 63); - negb = (uint32_t)((uint64_t)ccb >> 63); - cond_negate(a, len, nega); - cond_negate(b, len, negb); - return nega | (negb << 1); -} - -/* - * Compute: - * a <- (a*pa+b*pb)/(2^31) mod m - * b <- (a*qa+b*qb)/(2^31) mod m - * - * m0i is equal to -1/m[0] mod 2^31. - * - * Factors pa, pb, qa and qb must be at most 2^31 in absolute value. - * Source integers a and b must be nonnegative; top word is not allowed - * to contain an extra 32th bit. - */ -static void -co_reduce_mod(uint32_t *a, uint32_t *b, size_t len, - int64_t pa, int64_t pb, int64_t qa, int64_t qb, - const uint32_t *m, uint32_t m0i) -{ - size_t k; - int64_t cca, ccb; - uint32_t fa, fb; - - cca = 0; - ccb = 0; - fa = ((a[0] * (uint32_t)pa + b[0] * (uint32_t)pb) * m0i) & 0x7FFFFFFF; - fb = ((a[0] * (uint32_t)qa + b[0] * (uint32_t)qb) * m0i) & 0x7FFFFFFF; - for (k = 0; k < len; k ++) { - uint32_t wa, wb; - uint64_t za, zb; - uint64_t tta, ttb; - - /* - * In this loop, carries 'cca' and 'ccb' always fit on - * 33 bits (in absolute value). - */ - wa = a[k]; - wb = b[k]; - za = wa * (uint64_t)pa + wb * (uint64_t)pb - + m[k] * (uint64_t)fa + (uint64_t)cca; - zb = wa * (uint64_t)qa + wb * (uint64_t)qb - + m[k] * (uint64_t)fb + (uint64_t)ccb; - if (k > 0) { - a[k - 1] = (uint32_t)za & 0x7FFFFFFF; - b[k - 1] = (uint32_t)zb & 0x7FFFFFFF; - } - -#define M ((uint64_t)1 << 32) - tta = za >> 31; - ttb = zb >> 31; - tta = (tta ^ M) - M; - ttb = (ttb ^ M) - M; - cca = *(int64_t *)&tta; - ccb = *(int64_t *)&ttb; -#undef M - } - a[len - 1] = (uint32_t)cca; - b[len - 1] = (uint32_t)ccb; - - /* - * At this point: - * -m <= a < 2*m - * -m <= b < 2*m - * (this is a case of Montgomery reduction) - * The top word of 'a' and 'b' may have a 32-th bit set. - * We may have to add or subtract the modulus. - */ - finish_mod(a, len, m, (uint32_t)((uint64_t)cca >> 63)); - finish_mod(b, len, m, (uint32_t)((uint64_t)ccb >> 63)); -} - -/* see inner.h */ -uint32_t -br_i31_moddiv(uint32_t *x, const uint32_t *y, const uint32_t *m, uint32_t m0i, - uint32_t *t) -{ - /* - * Algorithm is an extended binary GCD. We maintain four values - * a, b, u and v, with the following invariants: - * - * a * x = y * u mod m - * b * x = y * v mod m - * - * Starting values are: - * - * a = y - * b = m - * u = x - * v = 0 - * - * The formal definition of the algorithm is a sequence of steps: - * - * - If a is even, then a <- a/2 and u <- u/2 mod m. - * - Otherwise, if b is even, then b <- b/2 and v <- v/2 mod m. - * - Otherwise, if a > b, then a <- (a-b)/2 and u <- (u-v)/2 mod m. - * - Otherwise, b <- (b-a)/2 and v <- (v-u)/2 mod m. - * - * Algorithm stops when a = b. At that point, they both are equal - * to GCD(y,m); the modular division succeeds if that value is 1. - * The result of the modular division is then u (or v: both are - * equal at that point). - * - * Each step makes either a or b shrink by at least one bit; hence, - * if m has bit length k bits, then 2k-2 steps are sufficient. - * - * - * Though complexity is quadratic in the size of m, the bit-by-bit - * processing is not very efficient. We can speed up processing by - * remarking that the decisions are taken based only on observation - * of the top and low bits of a and b. - * - * In the loop below, at each iteration, we use the two top words - * of a and b, and the low words of a and b, to compute reduction - * parameters pa, pb, qa and qb such that the new values for a - * and b are: - * - * a' = (a*pa + b*pb) / (2^31) - * b' = (a*qa + b*qb) / (2^31) - * - * the division being exact. - * - * Since the choices are based on the top words, they may be slightly - * off, requiring an optional correction: if a' < 0, then we replace - * pa with -pa, and pb with -pb. The total length of a and b is - * thus reduced by at least 30 bits at each iteration. - * - * The stopping conditions are still the same, though: when a - * and b become equal, they must be both odd (since m is odd, - * the GCD cannot be even), therefore the next operation is a - * subtraction, and one of the values becomes 0. At that point, - * nothing else happens, i.e. one value is stuck at 0, and the - * other one is the GCD. - */ - size_t len, k; - uint32_t *a, *b, *u, *v; - uint32_t num, r; - - len = (m[0] + 31) >> 5; - a = t; - b = a + len; - u = x + 1; - v = b + len; - memcpy(a, y + 1, len * sizeof *y); - memcpy(b, m + 1, len * sizeof *m); - memset(v, 0, len * sizeof *v); - - /* - * Loop below ensures that a and b are reduced by some bits each, - * for a total of at least 30 bits. - */ - for (num = ((m[0] - (m[0] >> 5)) << 1) + 30; num >= 30; num -= 30) { - size_t j; - uint32_t c0, c1; - uint32_t a0, a1, b0, b1; - uint64_t a_hi, b_hi; - uint32_t a_lo, b_lo; - int64_t pa, pb, qa, qb; - int i; - - /* - * Extract top words of a and b. If j is the highest - * index >= 1 such that a[j] != 0 or b[j] != 0, then we want - * (a[j] << 31) + a[j - 1], and (b[j] << 31) + b[j - 1]. - * If a and b are down to one word each, then we use a[0] - * and b[0]. - */ - c0 = (uint32_t)-1; - c1 = (uint32_t)-1; - a0 = 0; - a1 = 0; - b0 = 0; - b1 = 0; - j = len; - while (j -- > 0) { - uint32_t aw, bw; - - aw = a[j]; - bw = b[j]; - a0 ^= (a0 ^ aw) & c0; - a1 ^= (a1 ^ aw) & c1; - b0 ^= (b0 ^ bw) & c0; - b1 ^= (b1 ^ bw) & c1; - c1 = c0; - c0 &= (((aw | bw) + 0x7FFFFFFF) >> 31) - (uint32_t)1; - } - - /* - * If c1 = 0, then we grabbed two words for a and b. - * If c1 != 0 but c0 = 0, then we grabbed one word. It - * is not possible that c1 != 0 and c0 != 0, because that - * would mean that both integers are zero. - */ - a1 |= a0 & c1; - a0 &= ~c1; - b1 |= b0 & c1; - b0 &= ~c1; - a_hi = ((uint64_t)a0 << 31) + a1; - b_hi = ((uint64_t)b0 << 31) + b1; - a_lo = a[0]; - b_lo = b[0]; - - /* - * Compute reduction factors: - * - * a' = a*pa + b*pb - * b' = a*qa + b*qb - * - * such that a' and b' are both multiple of 2^31, but are - * only marginally larger than a and b. - */ - pa = 1; - pb = 0; - qa = 0; - qb = 1; - for (i = 0; i < 31; i ++) { - /* - * At each iteration: - * - * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi - * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi - * a <- a/2 if: a is even - * b <- b/2 if: a is odd, b is even - * - * We multiply a_lo and b_lo by 2 at each - * iteration, thus a division by 2 really is a - * non-multiplication by 2. - */ - uint32_t r, oa, ob, cAB, cBA, cA; - uint64_t rz; - - /* - * r = GT(a_hi, b_hi) - * But the GT() function works on uint32_t operands, - * so we inline a 64-bit version here. - */ - rz = b_hi - a_hi; - r = (uint32_t)((rz ^ ((a_hi ^ b_hi) - & (a_hi ^ rz))) >> 63); - - /* - * cAB = 1 if b must be subtracted from a - * cBA = 1 if a must be subtracted from b - * cA = 1 if a is divided by 2, 0 otherwise - * - * Rules: - * - * cAB and cBA cannot be both 1. - * if a is not divided by 2, b is. - */ - oa = (a_lo >> i) & 1; - ob = (b_lo >> i) & 1; - cAB = oa & ob & r; - cBA = oa & ob & NOT(r); - cA = cAB | NOT(oa); - - /* - * Conditional subtractions. - */ - a_lo -= b_lo & -cAB; - a_hi -= b_hi & -(uint64_t)cAB; - pa -= qa & -(int64_t)cAB; - pb -= qb & -(int64_t)cAB; - b_lo -= a_lo & -cBA; - b_hi -= a_hi & -(uint64_t)cBA; - qa -= pa & -(int64_t)cBA; - qb -= pb & -(int64_t)cBA; - - /* - * Shifting. - */ - a_lo += a_lo & (cA - 1); - pa += pa & ((int64_t)cA - 1); - pb += pb & ((int64_t)cA - 1); - a_hi ^= (a_hi ^ (a_hi >> 1)) & -(uint64_t)cA; - b_lo += b_lo & -cA; - qa += qa & -(int64_t)cA; - qb += qb & -(int64_t)cA; - b_hi ^= (b_hi ^ (b_hi >> 1)) & ((uint64_t)cA - 1); - } - - /* - * Replace a and b with new values a' and b'. - */ - r = co_reduce(a, b, len, pa, pb, qa, qb); - pa -= pa * ((r & 1) << 1); - pb -= pb * ((r & 1) << 1); - qa -= qa * (r & 2); - qb -= qb * (r & 2); - co_reduce_mod(u, v, len, pa, pb, qa, qb, m + 1, m0i); - } - - /* - * Now one of the arrays should be 0, and the other contains - * the GCD. If a is 0, then u is 0 as well, and v contains - * the division result. - * Result is correct if and only if GCD is 1. - */ - r = (a[0] | b[0]) ^ 1; - u[0] |= v[0]; - for (k = 1; k < len; k ++) { - r |= a[k] | b[k]; - u[k] |= v[k]; - } - return EQ0(r); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_modpow.c b/src/tls/bearssl/i31_modpow.c deleted file mode 100644 index e1a23e64b..000000000 --- a/src/tls/bearssl/i31_modpow.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_modpow(uint32_t *x, - const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2) -{ - size_t mlen; - uint32_t k; - - /* - * 'mlen' is the length of m[] expressed in bytes (including - * the "bit length" first field). - */ - mlen = ((m[0] + 63) >> 5) * sizeof m[0]; - - /* - * Throughout the algorithm: - * -- t1[] is in Montgomery representation; it contains x, x^2, - * x^4, x^8... - * -- The result is accumulated, in normal representation, in - * the x[] array. - * -- t2[] is used as destination buffer for each multiplication. - * - * Note that there is no need to call br_i32_from_monty(). - */ - memcpy(t1, x, mlen); - br_i31_to_monty(t1, m); - br_i31_zero(x, m[0]); - x[1] = 1; - for (k = 0; k < ((uint32_t)elen << 3); k ++) { - uint32_t ctl; - - ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; - br_i31_montymul(t2, x, t1, m, m0i); - CCOPY(ctl, x, t2, mlen); - br_i31_montymul(t2, t1, t1, m, m0i); - memcpy(t1, t2, mlen); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_modpow2.c b/src/tls/bearssl/i31_modpow2.c deleted file mode 100644 index b97b1c8fc..000000000 --- a/src/tls/bearssl/i31_modpow2.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_modpow_opt(uint32_t *x, - const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen) -{ - size_t mlen, mwlen; - uint32_t *t1, *t2, *base; - size_t u, v; - uint32_t acc; - int acc_len, win_len; - - /* - * Get modulus size. - */ - mwlen = (m[0] + 63) >> 5; - mlen = mwlen * sizeof m[0]; - mwlen += (mwlen & 1); - t1 = tmp; - t2 = tmp + mwlen; - - /* - * Compute possible window size, with a maximum of 5 bits. - * When the window has size 1 bit, we use a specific code - * that requires only two temporaries. Otherwise, for a - * window of k bits, we need 2^k+1 temporaries. - */ - if (twlen < (mwlen << 1)) { - return 0; - } - for (win_len = 5; win_len > 1; win_len --) { - if ((((uint32_t)1 << win_len) + 1) * mwlen <= twlen) { - break; - } - } - - /* - * Everything is done in Montgomery representation. - */ - br_i31_to_monty(x, m); - - /* - * Compute window contents. If the window has size one bit only, - * then t2 is set to x; otherwise, t2[0] is left untouched, and - * t2[k] is set to x^k (for k >= 1). - */ - if (win_len == 1) { - memcpy(t2, x, mlen); - } else { - memcpy(t2 + mwlen, x, mlen); - base = t2 + mwlen; - for (u = 2; u < ((unsigned)1 << win_len); u ++) { - br_i31_montymul(base + mwlen, base, x, m, m0i); - base += mwlen; - } - } - - /* - * We need to set x to 1, in Montgomery representation. This can - * be done efficiently by setting the high word to 1, then doing - * one word-sized shift. - */ - br_i31_zero(x, m[0]); - x[(m[0] + 31) >> 5] = 1; - br_i31_muladd_small(x, 0, m); - - /* - * We process bits from most to least significant. At each - * loop iteration, we have acc_len bits in acc. - */ - acc = 0; - acc_len = 0; - while (acc_len > 0 || elen > 0) { - int i, k; - uint32_t bits; - - /* - * Get the next bits. - */ - k = win_len; - if (acc_len < win_len) { - if (elen > 0) { - acc = (acc << 8) | *e ++; - elen --; - acc_len += 8; - } else { - k = acc_len; - } - } - bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); - acc_len -= k; - - /* - * We could get exactly k bits. Compute k squarings. - */ - for (i = 0; i < k; i ++) { - br_i31_montymul(t1, x, x, m, m0i); - memcpy(x, t1, mlen); - } - - /* - * Window lookup: we want to set t2 to the window - * lookup value, assuming the bits are non-zero. If - * the window length is 1 bit only, then t2 is - * already set; otherwise, we do a constant-time lookup. - */ - if (win_len > 1) { - br_i31_zero(t2, m[0]); - base = t2 + mwlen; - for (u = 1; u < ((uint32_t)1 << k); u ++) { - uint32_t mask; - - mask = -EQ(u, bits); - for (v = 1; v < mwlen; v ++) { - t2[v] |= mask & base[v]; - } - base += mwlen; - } - } - - /* - * Multiply with the looked-up value. We keep the - * product only if the exponent bits are not all-zero. - */ - br_i31_montymul(t1, x, t2, m, m0i); - CCOPY(NEQ(bits, 0), x, t1, mlen); - } - - /* - * Convert back from Montgomery representation, and exit. - */ - br_i31_from_monty(x, m, m0i); - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_montmul.c b/src/tls/bearssl/i31_montmul.c deleted file mode 100644 index d6ff97bdb..000000000 --- a/src/tls/bearssl/i31_montmul.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, - const uint32_t *m, uint32_t m0i) -{ - size_t len, len4, u, v; - uint64_t dh; - - len = (m[0] + 31) >> 5; - len4 = len & ~(size_t)3; - br_i31_zero(d, m[0]); - dh = 0; - for (u = 0; u < len; u ++) { - uint32_t f, xu; - uint64_t r, zh; - - xu = x[u + 1]; - f = MUL31_lo((d[1] + MUL31_lo(x[u + 1], y[1])), m0i); - - r = 0; - for (v = 0; v < len4; v += 4) { - uint64_t z; - - z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1]) - + MUL31(f, m[v + 1]) + r; - r = z >> 31; - d[v + 0] = (uint32_t)z & 0x7FFFFFFF; - z = (uint64_t)d[v + 2] + MUL31(xu, y[v + 2]) - + MUL31(f, m[v + 2]) + r; - r = z >> 31; - d[v + 1] = (uint32_t)z & 0x7FFFFFFF; - z = (uint64_t)d[v + 3] + MUL31(xu, y[v + 3]) - + MUL31(f, m[v + 3]) + r; - r = z >> 31; - d[v + 2] = (uint32_t)z & 0x7FFFFFFF; - z = (uint64_t)d[v + 4] + MUL31(xu, y[v + 4]) - + MUL31(f, m[v + 4]) + r; - r = z >> 31; - d[v + 3] = (uint32_t)z & 0x7FFFFFFF; - } - for (; v < len; v ++) { - uint64_t z; - - z = (uint64_t)d[v + 1] + MUL31(xu, y[v + 1]) - + MUL31(f, m[v + 1]) + r; - r = z >> 31; - d[v] = (uint32_t)z & 0x7FFFFFFF; - } - - zh = dh + r; - d[len] = (uint32_t)zh & 0x7FFFFFFF; - dh = zh >> 31; - } - - /* - * We must write back the bit length because it was overwritten in - * the loop (not overwriting it would require a test in the loop, - * which would yield bigger and slower code). - */ - d[0] = m[0]; - - /* - * d[] may still be greater than m[] at that point; notably, the - * 'dh' word may be non-zero. - */ - br_i31_sub(d, m, NEQ(dh, 0) | NOT(br_i31_sub(d, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_mulacc.c b/src/tls/bearssl/i31_mulacc.c deleted file mode 100644 index e0fb369b1..000000000 --- a/src/tls/bearssl/i31_mulacc.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - size_t alen, blen, u; - uint32_t dl, dh; - - alen = (a[0] + 31) >> 5; - blen = (b[0] + 31) >> 5; - - /* - * We want to add the two bit lengths, but these are encoded, - * which requires some extra care. - */ - dl = (a[0] & 31) + (b[0] & 31); - dh = (a[0] >> 5) + (b[0] >> 5); - d[0] = (dh << 5) + dl + (~(uint32_t)(dl - 31) >> 31); - - for (u = 0; u < blen; u ++) { - uint32_t f; - size_t v; - uint64_t cc; - - f = b[1 + u]; - cc = 0; - for (v = 0; v < alen; v ++) { - uint64_t z; - - z = (uint64_t)d[1 + u + v] + MUL31(f, a[1 + v]) + cc; - cc = z >> 31; - d[1 + u + v] = (uint32_t)z & 0x7FFFFFFF; - } - d[1 + u + alen] = (uint32_t)cc; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_muladd.c b/src/tls/bearssl/i31_muladd.c deleted file mode 100644 index b10e1a1a5..000000000 --- a/src/tls/bearssl/i31_muladd.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) -{ - uint32_t m_bitlen; - unsigned mblr; - size_t u, mlen; - uint32_t a0, a1, b0, hi, g, q, tb; - uint32_t under, over; - uint32_t cc; - - /* - * We can test on the modulus bit length since we accept to - * leak that length. - */ - m_bitlen = m[0]; - if (m_bitlen == 0) { - return; - } - if (m_bitlen <= 31) { - uint32_t lo; - - hi = x[1] >> 1; - lo = (x[1] << 31) | z; - x[1] = br_rem(hi, lo, m[1]); - return; - } - mlen = (m_bitlen + 31) >> 5; - mblr = (unsigned)m_bitlen & 31; - - /* - * Principle: we estimate the quotient (x*2^31+z)/m by - * doing a 64/32 division with the high words. - * - * Let: - * w = 2^31 - * a = (w*a0 + a1) * w^N + a2 - * b = b0 * w^N + b2 - * such that: - * 0 <= a0 < w - * 0 <= a1 < w - * 0 <= a2 < w^N - * w/2 <= b0 < w - * 0 <= b2 < w^N - * a < w*b - * I.e. the two top words of a are a0:a1, the top word of b is - * b0, we ensured that b0 is "full" (high bit set), and a is - * such that the quotient q = a/b fits on one word (0 <= q < w). - * - * If a = b*q + r (with 0 <= r < q), we can estimate q by - * doing an Euclidean division on the top words: - * a0*w+a1 = b0*u + v (with 0 <= v < b0) - * Then the following holds: - * 0 <= u <= w - * u-2 <= q <= u - */ - hi = x[mlen]; - if (mblr == 0) { - a0 = x[mlen]; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); - x[1] = z; - a1 = x[mlen]; - b0 = m[mlen]; - } else { - a0 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) - & 0x7FFFFFFF; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); - x[1] = z; - a1 = ((x[mlen] << (31 - mblr)) | (x[mlen - 1] >> mblr)) - & 0x7FFFFFFF; - b0 = ((m[mlen] << (31 - mblr)) | (m[mlen - 1] >> mblr)) - & 0x7FFFFFFF; - } - - /* - * We estimate a divisor q. If the quotient returned by br_div() - * is g: - * -- If a0 == b0 then g == 0; we want q = 0x7FFFFFFF. - * -- Otherwise: - * -- if g == 0 then we set q = 0; - * -- otherwise, we set q = g - 1. - * The properties described above then ensure that the true - * quotient is q-1, q or q+1. - * - * Take care that a0, a1 and b0 are 31-bit words, not 32-bit. We - * must adjust the parameters to br_div() accordingly. - */ - g = br_div(a0 >> 1, a1 | (a0 << 31), b0); - q = MUX(EQ(a0, b0), 0x7FFFFFFF, MUX(EQ(g, 0), 0, g - 1)); - - /* - * We subtract q*m from x (with the extra high word of value 'hi'). - * Since q may be off by 1 (in either direction), we may have to - * add or subtract m afterwards. - * - * The 'tb' flag will be true (1) at the end of the loop if the - * result is greater than or equal to the modulus (not counting - * 'hi' or the carry). - */ - cc = 0; - tb = 1; - for (u = 1; u <= mlen; u ++) { - uint32_t mw, zw, xw, nxw; - uint64_t zl; - - mw = m[u]; - zl = MUL31(mw, q) + cc; - cc = (uint32_t)(zl >> 31); - zw = (uint32_t)zl & (uint32_t)0x7FFFFFFF; - xw = x[u]; - nxw = xw - zw; - cc += nxw >> 31; - nxw &= 0x7FFFFFFF; - x[u] = nxw; - tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); - } - - /* - * If we underestimated q, then either cc < hi (one extra bit - * beyond the top array word), or cc == hi and tb is true (no - * extra bit, but the result is not lower than the modulus). In - * these cases we must subtract m once. - * - * Otherwise, we may have overestimated, which will show as - * cc > hi (thus a negative result). Correction is adding m once. - */ - over = GT(cc, hi); - under = ~over & (tb | LT(cc, hi)); - br_i31_add(x, m, over); - br_i31_sub(x, m, under); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_ninv31.c b/src/tls/bearssl/i31_ninv31.c deleted file mode 100644 index fb44f2eb8..000000000 --- a/src/tls/bearssl/i31_ninv31.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_ninv31(uint32_t x) -{ - uint32_t y; - - y = 2 - x; - y *= 2 - y * x; - y *= 2 - y * x; - y *= 2 - y * x; - y *= 2 - y * x; - return MUX(x & 1, -y, 0) & 0x7FFFFFFF; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_reduce.c b/src/tls/bearssl/i31_reduce.c deleted file mode 100644 index 672a48f90..000000000 --- a/src/tls/bearssl/i31_reduce.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) -{ - uint32_t m_bitlen, a_bitlen; - size_t mlen, alen, u; - - m_bitlen = m[0]; - mlen = (m_bitlen + 31) >> 5; - - x[0] = m_bitlen; - if (m_bitlen == 0) { - return; - } - - /* - * If the source is shorter, then simply copy all words from a[] - * and zero out the upper words. - */ - a_bitlen = a[0]; - alen = (a_bitlen + 31) >> 5; - if (a_bitlen < m_bitlen) { - memcpy(x + 1, a + 1, alen * sizeof *a); - for (u = alen; u < mlen; u ++) { - x[u + 1] = 0; - } - return; - } - - /* - * The source length is at least equal to that of the modulus. - * We must thus copy N-1 words, and input the remaining words - * one by one. - */ - memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); - x[mlen] = 0; - for (u = 1 + alen - mlen; u > 0; u --) { - br_i31_muladd_small(x, a[u], m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_rshift.c b/src/tls/bearssl/i31_rshift.c deleted file mode 100644 index 67f09a781..000000000 --- a/src/tls/bearssl/i31_rshift.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_rshift(uint32_t *x, int count) -{ - size_t u, len; - uint32_t r; - - len = (x[0] + 31) >> 5; - if (len == 0) { - return; - } - r = x[1] >> count; - for (u = 2; u <= len; u ++) { - uint32_t w; - - w = x[u]; - x[u - 1] = ((w << (31 - count)) | r) & 0x7FFFFFFF; - r = w >> count; - } - x[len] = r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_sub.c b/src/tls/bearssl/i31_sub.c deleted file mode 100644 index 39ae7bf0b..000000000 --- a/src/tls/bearssl/i31_sub.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 63) >> 5; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw - bw - cc; - cc = naw >> 31; - a[u] = MUX(ctl, naw & 0x7FFFFFFF, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i31_tmont.c b/src/tls/bearssl/i31_tmont.c deleted file mode 100644 index 8b9a310f0..000000000 --- a/src/tls/bearssl/i31_tmont.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i31_to_monty(uint32_t *x, const uint32_t *m) -{ - uint32_t k; - - for (k = (m[0] + 31) >> 5; k > 0; k --) { - br_i31_muladd_small(x, 0, m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_add.c b/src/tls/bearssl/i32_add.c deleted file mode 100644 index 20f2d2555..000000000 --- a/src/tls/bearssl/i32_add.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 63) >> 5; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw + bw + cc; - - /* - * Carry is 1 if naw < aw. Carry is also 1 if naw == aw - * AND the carry was already 1. - */ - cc = (cc & EQ(naw, aw)) | LT(naw, aw); - a[u] = MUX(ctl, naw, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_bitlen.c b/src/tls/bearssl/i32_bitlen.c deleted file mode 100644 index 34b229429..000000000 --- a/src/tls/bearssl/i32_bitlen.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_bit_length(uint32_t *x, size_t xlen) -{ - uint32_t tw, twk; - - tw = 0; - twk = 0; - while (xlen -- > 0) { - uint32_t w, c; - - c = EQ(tw, 0); - w = x[xlen]; - tw = MUX(c, w, tw); - twk = MUX(c, (uint32_t)xlen, twk); - } - return (twk << 5) + BIT_LENGTH(tw); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_decmod.c b/src/tls/bearssl/i32_decmod.c deleted file mode 100644 index 804e62115..000000000 --- a/src/tls/bearssl/i32_decmod.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_decode_mod(uint32_t *x, const void *src, size_t len, const uint32_t *m) -{ - const unsigned char *buf; - uint32_t r; - size_t u, v, mlen; - - buf = src; - - /* - * First pass: determine whether the value fits. The 'r' value - * will contain the comparison result, as 0x00000000 (value is - * equal to the modulus), 0x00000001 (value is greater than the - * modulus), or 0xFFFFFFFF (value is lower than the modulus). - */ - mlen = (m[0] + 7) >> 3; - r = 0; - for (u = (mlen > len) ? mlen : len; u > 0; u --) { - uint32_t mb, xb; - - v = u - 1; - if (v >= mlen) { - mb = 0; - } else { - mb = (m[1 + (v >> 2)] >> ((v & 3) << 3)) & 0xFF; - } - if (v >= len) { - xb = 0; - } else { - xb = buf[len - u]; - } - r = MUX(EQ(r, 0), (uint32_t)CMP(xb, mb), r); - } - - /* - * Only r == 0xFFFFFFFF is acceptable. We want to set r to 0xFF if - * the value fits, 0x00 otherwise. - */ - r >>= 24; - br_i32_zero(x, m[0]); - u = (mlen > len) ? len : mlen; - while (u > 0) { - uint32_t xb; - - xb = buf[len - u] & r; - u --; - x[1 + (u >> 2)] |= xb << ((u & 3) << 3); - } - return r >> 7; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_decode.c b/src/tls/bearssl/i32_decode.c deleted file mode 100644 index 19de24c1e..000000000 --- a/src/tls/bearssl/i32_decode.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_decode(uint32_t *x, const void *src, size_t len) -{ - const unsigned char *buf; - size_t u, v; - - buf = src; - u = len; - v = 1; - for (;;) { - if (u < 4) { - uint32_t w; - - if (u < 2) { - if (u == 0) { - break; - } else { - w = buf[0]; - } - } else { - if (u == 2) { - w = br_dec16be(buf); - } else { - w = ((uint32_t)buf[0] << 16) - | br_dec16be(buf + 1); - } - } - x[v ++] = w; - break; - } else { - u -= 4; - x[v ++] = br_dec32be(buf + u); - } - } - x[0] = br_i32_bit_length(x + 1, v - 1); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_decred.c b/src/tls/bearssl/i32_decred.c deleted file mode 100644 index 05098dc2b..000000000 --- a/src/tls/bearssl/i32_decred.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_decode_reduce(uint32_t *x, - const void *src, size_t len, const uint32_t *m) -{ - uint32_t m_bitlen; - size_t mblen, k, q; - const unsigned char *buf; - - m_bitlen = m[0]; - - /* - * Special case for an invalid modulus. - */ - if (m_bitlen == 0) { - x[0] = 0; - return; - } - - /* - * Clear the destination. - */ - br_i32_zero(x, m_bitlen); - - /* - * First decode directly as many bytes as possible without - * reduction, taking care to leave a number of bytes which - * is a multiple of 4. - */ - mblen = (m_bitlen + 7) >> 3; - k = mblen - 1; - - /* - * Up to k bytes can be safely decoded. - */ - if (k >= len) { - br_i32_decode(x, src, len); - x[0] = m_bitlen; - return; - } - - /* - * We want to first inject some bytes with direct decoding, - * then extra bytes by whole 32-bit words. First compute - * the size that should be injected that way. - */ - buf = src; - q = (len - k + 3) & ~(size_t)3; - - /* - * It may happen that this is more than what we already have - * (by at most 3 bytes). Such a case may happen only with - * a very short modulus. In that case, we must process the first - * bytes "manually". - */ - if (q > len) { - int i; - uint32_t w; - - w = 0; - for (i = 0; i < 4; i ++) { - w <<= 8; - if (q <= len) { - w |= buf[len - q]; - } - q --; - } - br_i32_muladd_small(x, w, m); - } else { - br_i32_decode(x, buf, len - q); - x[0] = m_bitlen; - } - - /* - * At that point, we have exactly q bytes to inject, and q is - * a multiple of 4. - */ - for (k = len - q; k < len; k += 4) { - br_i32_muladd_small(x, br_dec32be(buf + k), m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_div32.c b/src/tls/bearssl/i32_div32.c deleted file mode 100644 index b275effd9..000000000 --- a/src/tls/bearssl/i32_div32.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r) -{ - /* TODO: optimize this */ - uint32_t q; - uint32_t ch, cf; - int k; - - q = 0; - ch = EQ(hi, d); - hi = MUX(ch, 0, hi); - for (k = 31; k > 0; k --) { - int j; - uint32_t w, ctl, hi2, lo2; - - j = 32 - k; - w = (hi << j) | (lo >> k); - ctl = GE(w, d) | (hi >> k); - hi2 = (w - d) >> j; - lo2 = lo - (d << k); - hi = MUX(ctl, hi2, hi); - lo = MUX(ctl, lo2, lo); - q |= ctl << k; - } - cf = GE(lo, d) | hi; - q |= cf; - *r = MUX(cf, lo - d, lo); - return q; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_encode.c b/src/tls/bearssl/i32_encode.c deleted file mode 100644 index 6d1ddac44..000000000 --- a/src/tls/bearssl/i32_encode.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_encode(void *dst, size_t len, const uint32_t *x) -{ - unsigned char *buf; - size_t k; - - buf = dst; - - /* - * Compute the announced size of x in bytes; extra bytes are - * filled with zeros. - */ - k = (x[0] + 7) >> 3; - while (len > k) { - *buf ++ = 0; - len --; - } - - /* - * Now we use k as index within x[]. That index starts at 1; - * we initialize it to the topmost complete word, and process - * any remaining incomplete word. - */ - k = (len + 3) >> 2; - switch (len & 3) { - case 3: - *buf ++ = x[k] >> 16; - /* fall through */ - case 2: - *buf ++ = x[k] >> 8; - /* fall through */ - case 1: - *buf ++ = x[k]; - k --; - } - - /* - * Encode all complete words. - */ - while (k > 0) { - br_enc32be(buf, x[k]); - k --; - buf += 4; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_fmont.c b/src/tls/bearssl/i32_fmont.c deleted file mode 100644 index c0751b5b6..000000000 --- a/src/tls/bearssl/i32_fmont.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i) -{ - size_t len, u, v; - - len = (m[0] + 31) >> 5; - for (u = 0; u < len; u ++) { - uint32_t f; - uint64_t cc; - - f = x[1] * m0i; - cc = 0; - for (v = 0; v < len; v ++) { - uint64_t z; - - z = (uint64_t)x[v + 1] + MUL(f, m[v + 1]) + cc; - cc = z >> 32; - if (v != 0) { - x[v] = (uint32_t)z; - } - } - x[len] = (uint32_t)cc; - } - - /* - * We may have to do an extra subtraction, but only if the - * value in x[] is indeed greater than or equal to that of m[], - * which is why we must do two calls (first call computes the - * carry, second call performs the subtraction only if the carry - * is 0). - */ - br_i32_sub(x, m, NOT(br_i32_sub(x, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_iszero.c b/src/tls/bearssl/i32_iszero.c deleted file mode 100644 index d0b964623..000000000 --- a/src/tls/bearssl/i32_iszero.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_iszero(const uint32_t *x) -{ - uint32_t z; - size_t u; - - z = 0; - for (u = (x[0] + 31) >> 5; u > 0; u --) { - z |= x[u]; - } - return ~(z | -z) >> 31; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_modpow.c b/src/tls/bearssl/i32_modpow.c deleted file mode 100644 index 58c78adb9..000000000 --- a/src/tls/bearssl/i32_modpow.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_modpow(uint32_t *x, - const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2) -{ - size_t mlen; - uint32_t k; - - /* - * 'mlen' is the length of m[] expressed in bytes (including - * the "bit length" first field). - */ - mlen = ((m[0] + 63) >> 5) * sizeof m[0]; - - /* - * Throughout the algorithm: - * -- t1[] is in Montgomery representation; it contains x, x^2, - * x^4, x^8... - * -- The result is accumulated, in normal representation, in - * the x[] array. - * -- t2[] is used as destination buffer for each multiplication. - * - * Note that there is no need to call br_i32_from_monty(). - */ - memcpy(t1, x, mlen); - br_i32_to_monty(t1, m); - br_i32_zero(x, m[0]); - x[1] = 1; - for (k = 0; k < ((uint32_t)elen << 3); k ++) { - uint32_t ctl; - - ctl = (e[elen - 1 - (k >> 3)] >> (k & 7)) & 1; - br_i32_montymul(t2, x, t1, m, m0i); - CCOPY(ctl, x, t2, mlen); - br_i32_montymul(t2, t1, t1, m, m0i); - memcpy(t1, t2, mlen); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_montmul.c b/src/tls/bearssl/i32_montmul.c deleted file mode 100644 index 4ba5d4d60..000000000 --- a/src/tls/bearssl/i32_montmul.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, - const uint32_t *m, uint32_t m0i) -{ - size_t len, u, v; - uint64_t dh; - - len = (m[0] + 31) >> 5; - br_i32_zero(d, m[0]); - dh = 0; - for (u = 0; u < len; u ++) { - uint32_t f, xu; - uint64_t r1, r2, zh; - - xu = x[u + 1]; - f = (d[1] + x[u + 1] * y[1]) * m0i; - r1 = 0; - r2 = 0; - for (v = 0; v < len; v ++) { - uint64_t z; - uint32_t t; - - z = (uint64_t)d[v + 1] + MUL(xu, y[v + 1]) + r1; - r1 = z >> 32; - t = (uint32_t)z; - z = (uint64_t)t + MUL(f, m[v + 1]) + r2; - r2 = z >> 32; - if (v != 0) { - d[v] = (uint32_t)z; - } - } - zh = dh + r1 + r2; - d[len] = (uint32_t)zh; - dh = zh >> 32; - } - - /* - * d[] may still be greater than m[] at that point; notably, the - * 'dh' word may be non-zero. - */ - br_i32_sub(d, m, NEQ(dh, 0) | NOT(br_i32_sub(d, m, 0))); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_mulacc.c b/src/tls/bearssl/i32_mulacc.c deleted file mode 100644 index 4119d96ca..000000000 --- a/src/tls/bearssl/i32_mulacc.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b) -{ - size_t alen, blen, u; - - alen = (a[0] + 31) >> 5; - blen = (b[0] + 31) >> 5; - d[0] = a[0] + b[0]; - for (u = 0; u < blen; u ++) { - uint32_t f; - size_t v; - uint64_t cc; - - f = b[1 + u]; - cc = 0; - for (v = 0; v < alen; v ++) { - uint64_t z; - - z = (uint64_t)d[1 + u + v] + MUL(f, a[1 + v]) + cc; - cc = z >> 32; - d[1 + u + v] = (uint32_t)z; - } - d[1 + u + alen] = (uint32_t)cc; - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_muladd.c b/src/tls/bearssl/i32_muladd.c deleted file mode 100644 index 922881ff9..000000000 --- a/src/tls/bearssl/i32_muladd.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m) -{ - uint32_t m_bitlen; - size_t u, mlen; - uint32_t a0, a1, b0, hi, g, q, tb; - uint32_t chf, clow, under, over; - uint64_t cc; - - /* - * We can test on the modulus bit length since we accept to - * leak that length. - */ - m_bitlen = m[0]; - if (m_bitlen == 0) { - return; - } - if (m_bitlen <= 32) { - x[1] = br_rem(x[1], z, m[1]); - return; - } - mlen = (m_bitlen + 31) >> 5; - - /* - * Principle: we estimate the quotient (x*2^32+z)/m by - * doing a 64/32 division with the high words. - * - * Let: - * w = 2^32 - * a = (w*a0 + a1) * w^N + a2 - * b = b0 * w^N + b2 - * such that: - * 0 <= a0 < w - * 0 <= a1 < w - * 0 <= a2 < w^N - * w/2 <= b0 < w - * 0 <= b2 < w^N - * a < w*b - * I.e. the two top words of a are a0:a1, the top word of b is - * b0, we ensured that b0 is "full" (high bit set), and a is - * such that the quotient q = a/b fits on one word (0 <= q < w). - * - * If a = b*q + r (with 0 <= r < q), we can estimate q by - * doing an Euclidean division on the top words: - * a0*w+a1 = b0*u + v (with 0 <= v < w) - * Then the following holds: - * 0 <= u <= w - * u-2 <= q <= u - */ - a0 = br_i32_word(x, m_bitlen - 32); - hi = x[mlen]; - memmove(x + 2, x + 1, (mlen - 1) * sizeof *x); - x[1] = z; - a1 = br_i32_word(x, m_bitlen - 32); - b0 = br_i32_word(m, m_bitlen - 32); - - /* - * We estimate a divisor q. If the quotient returned by br_div() - * is g: - * -- If a0 == b0 then g == 0; we want q = 0xFFFFFFFF. - * -- Otherwise: - * -- if g == 0 then we set q = 0; - * -- otherwise, we set q = g - 1. - * The properties described above then ensure that the true - * quotient is q-1, q or q+1. - */ - g = br_div(a0, a1, b0); - q = MUX(EQ(a0, b0), 0xFFFFFFFF, MUX(EQ(g, 0), 0, g - 1)); - - /* - * We subtract q*m from x (with the extra high word of value 'hi'). - * Since q may be off by 1 (in either direction), we may have to - * add or subtract m afterwards. - * - * The 'tb' flag will be true (1) at the end of the loop if the - * result is greater than or equal to the modulus (not counting - * 'hi' or the carry). - */ - cc = 0; - tb = 1; - for (u = 1; u <= mlen; u ++) { - uint32_t mw, zw, xw, nxw; - uint64_t zl; - - mw = m[u]; - zl = MUL(mw, q) + cc; - cc = (uint32_t)(zl >> 32); - zw = (uint32_t)zl; - xw = x[u]; - nxw = xw - zw; - cc += (uint64_t)GT(nxw, xw); - x[u] = nxw; - tb = MUX(EQ(nxw, mw), tb, GT(nxw, mw)); - } - - /* - * If we underestimated q, then either cc < hi (one extra bit - * beyond the top array word), or cc == hi and tb is true (no - * extra bit, but the result is not lower than the modulus). In - * these cases we must subtract m once. - * - * Otherwise, we may have overestimated, which will show as - * cc > hi (thus a negative result). Correction is adding m once. - */ - chf = (uint32_t)(cc >> 32); - clow = (uint32_t)cc; - over = chf | GT(clow, hi); - under = ~over & (tb | (~chf & LT(clow, hi))); - br_i32_add(x, m, over); - br_i32_sub(x, m, under); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_ninv32.c b/src/tls/bearssl/i32_ninv32.c deleted file mode 100644 index d691a0cec..000000000 --- a/src/tls/bearssl/i32_ninv32.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_ninv32(uint32_t x) -{ - uint32_t y; - - y = 2 - x; - y *= 2 - y * x; - y *= 2 - y * x; - y *= 2 - y * x; - y *= 2 - y * x; - return MUX(x & 1, -y, 0); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_reduce.c b/src/tls/bearssl/i32_reduce.c deleted file mode 100644 index 3c6ea9aa2..000000000 --- a/src/tls/bearssl/i32_reduce.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m) -{ - uint32_t m_bitlen, a_bitlen; - size_t mlen, alen, u; - - m_bitlen = m[0]; - mlen = (m_bitlen + 31) >> 5; - - x[0] = m_bitlen; - if (m_bitlen == 0) { - return; - } - - /* - * If the source is shorter, then simply copy all words from a[] - * and zero out the upper words. - */ - a_bitlen = a[0]; - alen = (a_bitlen + 31) >> 5; - if (a_bitlen < m_bitlen) { - memcpy(x + 1, a + 1, alen * sizeof *a); - for (u = alen; u < mlen; u ++) { - x[u + 1] = 0; - } - return; - } - - /* - * The source length is at least equal to that of the modulus. - * We must thus copy N-1 words, and input the remaining words - * one by one. - */ - memcpy(x + 1, a + 2 + (alen - mlen), (mlen - 1) * sizeof *a); - x[mlen] = 0; - for (u = 1 + alen - mlen; u > 0; u --) { - br_i32_muladd_small(x, a[u], m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_sub.c b/src/tls/bearssl/i32_sub.c deleted file mode 100644 index 58048ecbd..000000000 --- a/src/tls/bearssl/i32_sub.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl) -{ - uint32_t cc; - size_t u, m; - - cc = 0; - m = (a[0] + 63) >> 5; - for (u = 1; u < m; u ++) { - uint32_t aw, bw, naw; - - aw = a[u]; - bw = b[u]; - naw = aw - bw - cc; - - /* - * Carry is 1 if naw > aw. Carry is 1 also if naw == aw - * AND the carry was already 1. - */ - cc = (cc & EQ(naw, aw)) | GT(naw, aw); - a[u] = MUX(ctl, naw, aw); - } - return cc; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i32_tmont.c b/src/tls/bearssl/i32_tmont.c deleted file mode 100644 index be9c003ff..000000000 --- a/src/tls/bearssl/i32_tmont.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_i32_to_monty(uint32_t *x, const uint32_t *m) -{ - uint32_t k; - - for (k = (m[0] + 31) >> 5; k > 0; k --) { - br_i32_muladd_small(x, 0, m); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/i62_modpow2.c b/src/tls/bearssl/i62_modpow2.c deleted file mode 100644 index 674101c7f..000000000 --- a/src/tls/bearssl/i62_modpow2.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -#if BR_INT128 - -/* - * Compute x*y+v1+v2. Operands are 64-bit, and result is 128-bit, with - * high word in "hi" and low word in "lo". - */ -#define FMA1(hi, lo, x, y, v1, v2) do { \ - unsigned __int128 fmaz; \ - fmaz = (unsigned __int128)(x) * (unsigned __int128)(y) \ - + (unsigned __int128)(v1) + (unsigned __int128)(v2); \ - (hi) = (uint64_t)(fmaz >> 64); \ - (lo) = (uint64_t)fmaz; \ - } while (0) - -/* - * Compute x1*y1+x2*y2+v1+v2. Operands are 64-bit, and result is 128-bit, - * with high word in "hi" and low word in "lo". - * - * Callers should ensure that the two inner products, and the v1 and v2 - * operands, are multiple of 4 (this is not used by this specific definition - * but may help other implementations). - */ -#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ - unsigned __int128 fmaz; \ - fmaz = (unsigned __int128)(x1) * (unsigned __int128)(y1) \ - + (unsigned __int128)(x2) * (unsigned __int128)(y2) \ - + (unsigned __int128)(v1) + (unsigned __int128)(v2); \ - (hi) = (uint64_t)(fmaz >> 64); \ - (lo) = (uint64_t)fmaz; \ - } while (0) - -#elif BR_UMUL128 - -#include - -#define FMA1(hi, lo, x, y, v1, v2) do { \ - uint64_t fmahi, fmalo; \ - unsigned char fmacc; \ - fmalo = _umul128((x), (y), &fmahi); \ - fmacc = _addcarry_u64(0, fmalo, (v1), &fmalo); \ - _addcarry_u64(fmacc, fmahi, 0, &fmahi); \ - fmacc = _addcarry_u64(0, fmalo, (v2), &(lo)); \ - _addcarry_u64(fmacc, fmahi, 0, &(hi)); \ - } while (0) - -/* - * Normally we should use _addcarry_u64() for FMA2 too, but it makes - * Visual Studio crash. Instead we use this version, which leverages - * the fact that the vx operands, and the products, are multiple of 4. - * This is unfortunately slower. - */ -#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ - uint64_t fma1hi, fma1lo; \ - uint64_t fma2hi, fma2lo; \ - uint64_t fmatt; \ - fma1lo = _umul128((x1), (y1), &fma1hi); \ - fma2lo = _umul128((x2), (y2), &fma2hi); \ - fmatt = (fma1lo >> 2) + (fma2lo >> 2) \ - + ((v1) >> 2) + ((v2) >> 2); \ - (lo) = fmatt << 2; \ - (hi) = fma1hi + fma2hi + (fmatt >> 62); \ - } while (0) - -/* - * The FMA2 macro definition we would prefer to use, but it triggers - * an internal compiler error in Visual Studio 2015. - * -#define FMA2(hi, lo, x1, y1, x2, y2, v1, v2) do { \ - uint64_t fma1hi, fma1lo; \ - uint64_t fma2hi, fma2lo; \ - unsigned char fmacc; \ - fma1lo = _umul128((x1), (y1), &fma1hi); \ - fma2lo = _umul128((x2), (y2), &fma2hi); \ - fmacc = _addcarry_u64(0, fma1lo, (v1), &fma1lo); \ - _addcarry_u64(fmacc, fma1hi, 0, &fma1hi); \ - fmacc = _addcarry_u64(0, fma2lo, (v2), &fma2lo); \ - _addcarry_u64(fmacc, fma2hi, 0, &fma2hi); \ - fmacc = _addcarry_u64(0, fma1lo, fma2lo, &(lo)); \ - _addcarry_u64(fmacc, fma1hi, fma2hi, &(hi)); \ - } while (0) - */ - -#endif - -#define MASK62 ((uint64_t)0x3FFFFFFFFFFFFFFF) -#define MUL62_lo(x, y) (((uint64_t)(x) * (uint64_t)(y)) & MASK62) - -/* - * Subtract b from a, and return the final carry. If 'ctl32' is 0, then - * a[] is kept unmodified, but the final carry is still computed and - * returned. - */ -static uint32_t -i62_sub(uint64_t *a, const uint64_t *b, size_t num, uint32_t ctl32) -{ - uint64_t cc, mask; - size_t u; - - cc = 0; - ctl32 = -ctl32; - mask = (uint64_t)ctl32 | ((uint64_t)ctl32 << 32); - for (u = 0; u < num; u ++) { - uint64_t aw, bw, dw; - - aw = a[u]; - bw = b[u]; - dw = aw - bw - cc; - cc = dw >> 63; - dw &= MASK62; - a[u] = aw ^ (mask & (dw ^ aw)); - } - return (uint32_t)cc; -} - -/* - * Montgomery multiplication, over arrays of 62-bit values. The - * destination array (d) must be distinct from the other operands - * (x, y and m). All arrays are in little-endian format (least - * significant word comes first) over 'num' words. - */ -static void -montymul(uint64_t *d, const uint64_t *x, const uint64_t *y, - const uint64_t *m, size_t num, uint64_t m0i) -{ - uint64_t dh; - size_t u, num4; - - num4 = 1 + ((num - 1) & ~(size_t)3); - memset(d, 0, num * sizeof *d); - dh = 0; - for (u = 0; u < num; u ++) { - size_t v; - uint64_t f, xu; - uint64_t r, zh; - uint64_t hi, lo; - - xu = x[u] << 2; - f = MUL62_lo(d[0] + MUL62_lo(x[u], y[0]), m0i) << 2; - - FMA2(hi, lo, xu, y[0], f, m[0], d[0] << 2, 0); - r = hi; - - for (v = 1; v < num4; v += 4) { - FMA2(hi, lo, xu, y[v + 0], - f, m[v + 0], d[v + 0] << 2, r << 2); - r = hi + (r >> 62); - d[v - 1] = lo >> 2; - FMA2(hi, lo, xu, y[v + 1], - f, m[v + 1], d[v + 1] << 2, r << 2); - r = hi + (r >> 62); - d[v + 0] = lo >> 2; - FMA2(hi, lo, xu, y[v + 2], - f, m[v + 2], d[v + 2] << 2, r << 2); - r = hi + (r >> 62); - d[v + 1] = lo >> 2; - FMA2(hi, lo, xu, y[v + 3], - f, m[v + 3], d[v + 3] << 2, r << 2); - r = hi + (r >> 62); - d[v + 2] = lo >> 2; - } - for (; v < num; v ++) { - FMA2(hi, lo, xu, y[v], f, m[v], d[v] << 2, r << 2); - r = hi + (r >> 62); - d[v - 1] = lo >> 2; - } - - zh = dh + r; - d[num - 1] = zh & MASK62; - dh = zh >> 62; - } - i62_sub(d, m, num, (uint32_t)dh | NOT(i62_sub(d, m, num, 0))); -} - -/* - * Conversion back from Montgomery representation. - */ -static void -frommonty(uint64_t *x, const uint64_t *m, size_t num, uint64_t m0i) -{ - size_t u, v; - - for (u = 0; u < num; u ++) { - uint64_t f, cc; - - f = MUL62_lo(x[0], m0i) << 2; - cc = 0; - for (v = 0; v < num; v ++) { - uint64_t hi, lo; - - FMA1(hi, lo, f, m[v], x[v] << 2, cc); - cc = hi << 2; - if (v != 0) { - x[v - 1] = lo >> 2; - } - } - x[num - 1] = cc >> 2; - } - i62_sub(x, m, num, NOT(i62_sub(x, m, num, 0))); -} - -/* see inner.h */ -uint32_t -br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, - const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen) -{ - size_t u, mw31num, mw62num; - uint64_t *x, *m, *t1, *t2; - uint64_t m0i; - uint32_t acc; - int win_len, acc_len; - - /* - * Get modulus size, in words. - */ - mw31num = (m31[0] + 31) >> 5; - mw62num = (mw31num + 1) >> 1; - - /* - * In order to apply this function, we must have enough room to - * copy the operand and modulus into the temporary array, along - * with at least two temporaries. If there is not enough room, - * switch to br_i31_modpow(). We also use br_i31_modpow() if the - * modulus length is not at least four words (94 bits or more). - */ - if (mw31num < 4 || (mw62num << 2) > twlen) { - /* - * We assume here that we can split an aligned uint64_t - * into two properly aligned uint32_t. Since both types - * are supposed to have an exact width with no padding, - * then this property must hold. - */ - size_t txlen; - - txlen = mw31num + 1; - if (twlen < txlen) { - return 0; - } - br_i31_modpow(x31, e, elen, m31, m0i31, - (uint32_t *)tmp, (uint32_t *)tmp + txlen); - return 1; - } - - /* - * Convert x to Montgomery representation: this means that - * we replace x with x*2^z mod m, where z is the smallest multiple - * of the word size such that 2^z >= m. We want to reuse the 31-bit - * functions here (for constant-time operation), but we need z - * for a 62-bit word size. - */ - for (u = 0; u < mw62num; u ++) { - br_i31_muladd_small(x31, 0, m31); - br_i31_muladd_small(x31, 0, m31); - } - - /* - * Assemble operands into arrays of 62-bit words. Note that - * all the arrays of 62-bit words that we will handle here - * are without any leading size word. - * - * We also adjust tmp and twlen to account for the words used - * for these extra arrays. - */ - m = tmp; - x = tmp + mw62num; - tmp += (mw62num << 1); - twlen -= (mw62num << 1); - for (u = 0; u < mw31num; u += 2) { - size_t v; - - v = u >> 1; - if ((u + 1) == mw31num) { - m[v] = (uint64_t)m31[u + 1]; - x[v] = (uint64_t)x31[u + 1]; - } else { - m[v] = (uint64_t)m31[u + 1] - + ((uint64_t)m31[u + 2] << 31); - x[v] = (uint64_t)x31[u + 1] - + ((uint64_t)x31[u + 2] << 31); - } - } - - /* - * Compute window size. We support windows up to 5 bits; for a - * window of size k bits, we need 2^k+1 temporaries (for k = 1, - * we use special code that uses only 2 temporaries). - */ - for (win_len = 5; win_len > 1; win_len --) { - if ((((uint32_t)1 << win_len) + 1) * mw62num <= twlen) { - break; - } - } - - t1 = tmp; - t2 = tmp + mw62num; - - /* - * Compute m0i, which is equal to -(1/m0) mod 2^62. We were - * provided with m0i31, which already fulfills this property - * modulo 2^31; the single expression below is then sufficient. - */ - m0i = (uint64_t)m0i31; - m0i = MUL62_lo(m0i, (uint64_t)2 + MUL62_lo(m0i, m[0])); - - /* - * Compute window contents. If the window has size one bit only, - * then t2 is set to x; otherwise, t2[0] is left untouched, and - * t2[k] is set to x^k (for k >= 1). - */ - if (win_len == 1) { - memcpy(t2, x, mw62num * sizeof *x); - } else { - uint64_t *base; - - memcpy(t2 + mw62num, x, mw62num * sizeof *x); - base = t2 + mw62num; - for (u = 2; u < ((unsigned)1 << win_len); u ++) { - montymul(base + mw62num, base, x, m, mw62num, m0i); - base += mw62num; - } - } - - /* - * Set x to 1, in Montgomery representation. We again use the - * 31-bit code. - */ - br_i31_zero(x31, m31[0]); - x31[(m31[0] + 31) >> 5] = 1; - br_i31_muladd_small(x31, 0, m31); - if (mw31num & 1) { - br_i31_muladd_small(x31, 0, m31); - } - for (u = 0; u < mw31num; u += 2) { - size_t v; - - v = u >> 1; - if ((u + 1) == mw31num) { - x[v] = (uint64_t)x31[u + 1]; - } else { - x[v] = (uint64_t)x31[u + 1] - + ((uint64_t)x31[u + 2] << 31); - } - } - - /* - * We process bits from most to least significant. At each - * loop iteration, we have acc_len bits in acc. - */ - acc = 0; - acc_len = 0; - while (acc_len > 0 || elen > 0) { - int i, k; - uint32_t bits; - uint64_t mask1, mask2; - - /* - * Get the next bits. - */ - k = win_len; - if (acc_len < win_len) { - if (elen > 0) { - acc = (acc << 8) | *e ++; - elen --; - acc_len += 8; - } else { - k = acc_len; - } - } - bits = (acc >> (acc_len - k)) & (((uint32_t)1 << k) - 1); - acc_len -= k; - - /* - * We could get exactly k bits. Compute k squarings. - */ - for (i = 0; i < k; i ++) { - montymul(t1, x, x, m, mw62num, m0i); - memcpy(x, t1, mw62num * sizeof *x); - } - - /* - * Window lookup: we want to set t2 to the window - * lookup value, assuming the bits are non-zero. If - * the window length is 1 bit only, then t2 is - * already set; otherwise, we do a constant-time lookup. - */ - if (win_len > 1) { - uint64_t *base; - - memset(t2, 0, mw62num * sizeof *t2); - base = t2 + mw62num; - for (u = 1; u < ((uint32_t)1 << k); u ++) { - uint64_t mask; - size_t v; - - mask = -(uint64_t)EQ(u, bits); - for (v = 0; v < mw62num; v ++) { - t2[v] |= mask & base[v]; - } - base += mw62num; - } - } - - /* - * Multiply with the looked-up value. We keep the product - * only if the exponent bits are not all-zero. - */ - montymul(t1, x, t2, m, mw62num, m0i); - mask1 = -(uint64_t)EQ(bits, 0); - mask2 = ~mask1; - for (u = 0; u < mw62num; u ++) { - x[u] = (mask1 & x[u]) | (mask2 & t1[u]); - } - } - - /* - * Convert back from Montgomery representation. - */ - frommonty(x, m, mw62num, m0i); - - /* - * Convert result into 31-bit words. - */ - for (u = 0; u < mw31num; u += 2) { - uint64_t zw; - - zw = x[u >> 1]; - x31[u + 1] = (uint32_t)zw & 0x7FFFFFFF; - if ((u + 1) < mw31num) { - x31[u + 2] = (uint32_t)(zw >> 31); - } - } - return 1; -} - -#else - -/* see inner.h */ -uint32_t -br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, - const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen) -{ - size_t mwlen; - - mwlen = (m31[0] + 63) >> 5; - if (twlen < mwlen) { - return 0; - } - return br_i31_modpow_opt(x31, e, elen, m31, m0i31, - (uint32_t *)tmp, twlen << 1); -} - -#endif - -/* see inner.h */ -uint32_t -br_i62_modpow_opt_as_i31(uint32_t *x31, const unsigned char *e, size_t elen, - const uint32_t *m31, uint32_t m0i31, uint32_t *tmp, size_t twlen) -{ - /* - * As documented, this function expects the 'tmp' argument to be - * 64-bit aligned. This is OK since this function is internal (it - * is not part of BearSSL's public API). - */ - return br_i62_modpow_opt(x31, e, elen, m31, m0i31, - (uint64_t *)tmp, twlen >> 1); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/inner.h b/src/tls/bearssl/inner.h deleted file mode 100644 index a73fa54eb..000000000 --- a/src/tls/bearssl/inner.h +++ /dev/null @@ -1,2532 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef INNER_H__ -#define INNER_H__ - -#include -#include - -#include "config.h" -#include "bearssl.h" - -/* - * On MSVC, disable the warning about applying unary minus on an - * unsigned type: it is standard, we do it all the time, and for - * good reasons. - */ -#if _MSC_VER -#pragma warning( disable : 4146 ) -#endif - -/* - * Maximum size for a RSA modulus (in bits). Allocated stack buffers - * depend on that size, so this value should be kept small. Currently, - * 2048-bit RSA keys offer adequate security, and should still do so for - * the next few decades; however, a number of widespread PKI have - * already set their root keys to RSA-4096, so we should be able to - * process such keys. - * - * This value MUST be a multiple of 64. This value MUST NOT exceed 47666 - * (some computations in RSA key generation rely on the factor size being - * no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a - * lot of sense anyway. - */ -#define BR_MAX_RSA_SIZE 4096 - -/* - * Minimum size for a RSA modulus (in bits); this value is used only to - * filter out invalid parameters for key pair generation. Normally, - * applications should not use RSA keys smaller than 2048 bits; but some - * specific cases might need shorter keys, for legacy or research - * purposes. - */ -#define BR_MIN_RSA_SIZE 512 - -/* - * Maximum size for a RSA factor (in bits). This is for RSA private-key - * operations. Default is to support factors up to a bit more than half - * the maximum modulus size. - * - * This value MUST be a multiple of 32. - */ -#define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1) - -/* - * Maximum size for an EC curve (modulus or order), in bits. Size of - * stack buffers depends on that parameter. This size MUST be a multiple - * of 8 (so that decoding an integer with that many bytes does not - * overflow). - */ -#define BR_MAX_EC_SIZE 528 - -/* - * Some macros to recognize the current architecture. Right now, we are - * interested into automatically recognizing architecture with efficient - * 64-bit types so that we may automatically use implementations that - * use 64-bit registers in that case. Future versions may detect, e.g., - * availability of SSE2 intrinsics. - * - * If 'unsigned long' is a 64-bit type, then we assume that 64-bit types - * are efficient. Otherwise, we rely on macros that depend on compiler, - * OS and architecture. In any case, failure to detect the architecture - * as 64-bit means that the 32-bit code will be used, and that code - * works also on 64-bit architectures (the 64-bit code may simply be - * more efficient). - * - * The test on 'unsigned long' should already catch most cases, the one - * notable exception being Windows code where 'unsigned long' is kept to - * 32-bit for compatibility with all the legacy code that liberally uses - * the 'DWORD' type for 32-bit values. - * - * Macro names are taken from: http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros - */ -#ifndef BR_64 -#if ((ULONG_MAX >> 31) >> 31) == 3 -#define BR_64 1 -#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64) -#define BR_64 1 -#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \ - || defined(__64BIT__) || defined(_LP64) || defined(__LP64__) -#define BR_64 1 -#elif defined(__sparc64__) -#define BR_64 1 -#elif defined(__x86_64__) || defined(_M_X64) -#define BR_64 1 -#endif -#endif - -/* - * Set BR_LOMUL on platforms where it makes sense. - */ -#ifndef BR_LOMUL -#if BR_ARMEL_CORTEXM_GCC -#define BR_LOMUL 1 -#endif -#endif - -/* - * Architecture detection. - */ -#ifndef BR_i386 -#if __i386__ || _M_IX86 -#define BR_i386 1 -#endif -#endif - -#ifndef BR_amd64 -#if __x86_64__ || _M_X64 -#define BR_amd64 1 -#endif -#endif - -/* - * Compiler brand and version. - * - * Implementations that use intrinsics need to detect the compiler type - * and version because some specific actions may be needed to activate - * the corresponding opcodes, both for header inclusion, and when using - * them in a function. - * - * BR_GCC, BR_CLANG and BR_MSC will be set to 1 for, respectively, GCC, - * Clang and MS Visual C. For each of them, sub-macros will be defined - * for versions; each sub-macro is set whenever the compiler version is - * at least as recent as the one corresponding to the macro. - */ - -/* - * GCC thresholds are on versions 4.4 to 4.9 and 5.0. - */ -#ifndef BR_GCC -#if __GNUC__ && !__clang__ -#define BR_GCC 1 - -#if __GNUC__ > 4 -#define BR_GCC_5_0 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 -#define BR_GCC_4_9 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8 -#define BR_GCC_4_8 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7 -#define BR_GCC_4_7 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6 -#define BR_GCC_4_6 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5 -#define BR_GCC_4_5 1 -#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 4 -#define BR_GCC_4_4 1 -#endif - -#if BR_GCC_5_0 -#define BR_GCC_4_9 1 -#endif -#if BR_GCC_4_9 -#define BR_GCC_4_8 1 -#endif -#if BR_GCC_4_8 -#define BR_GCC_4_7 1 -#endif -#if BR_GCC_4_7 -#define BR_GCC_4_6 1 -#endif -#if BR_GCC_4_6 -#define BR_GCC_4_5 1 -#endif -#if BR_GCC_4_5 -#define BR_GCC_4_4 1 -#endif - -#endif -#endif - -/* - * Clang thresholds are on versions 3.7.0 and 3.8.0. - */ -#ifndef BR_CLANG -#if __clang__ -#define BR_CLANG 1 - -#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8) -#define BR_CLANG_3_8 1 -#elif __clang_major__ == 3 && __clang_minor__ >= 7 -#define BR_CLANG_3_7 1 -#endif - -#if BR_CLANG_3_8 -#define BR_CLANG_3_7 1 -#endif - -#endif -#endif - -/* - * MS Visual C thresholds are on Visual Studio 2005 to 2015. - */ -#ifndef BR_MSC -#if _MSC_VER -#define BR_MSC 1 - -#if _MSC_VER >= 1900 -#define BR_MSC_2015 1 -#elif _MSC_VER >= 1800 -#define BR_MSC_2013 1 -#elif _MSC_VER >= 1700 -#define BR_MSC_2012 1 -#elif _MSC_VER >= 1600 -#define BR_MSC_2010 1 -#elif _MSC_VER >= 1500 -#define BR_MSC_2008 1 -#elif _MSC_VER >= 1400 -#define BR_MSC_2005 1 -#endif - -#if BR_MSC_2015 -#define BR_MSC_2013 1 -#endif -#if BR_MSC_2013 -#define BR_MSC_2012 1 -#endif -#if BR_MSC_2012 -#define BR_MSC_2010 1 -#endif -#if BR_MSC_2010 -#define BR_MSC_2008 1 -#endif -#if BR_MSC_2008 -#define BR_MSC_2005 1 -#endif - -#endif -#endif - -/* - * GCC 4.4+ and Clang 3.7+ allow tagging specific functions with a - * 'target' attribute that activates support for specific opcodes. - */ -#if BR_GCC_4_4 || BR_CLANG_3_7 -#define BR_TARGET(x) __attribute__((target(x))) -#else -#define BR_TARGET(x) -#endif - -/* - * AES-NI intrinsics are available on x86 (32-bit and 64-bit) with - * GCC 4.8+, Clang 3.7+ and MSC 2012+. - */ -#ifndef BR_AES_X86NI -#if (BR_i386 || BR_amd64) && (BR_GCC_4_8 || BR_CLANG_3_7 || BR_MSC_2012) -#define BR_AES_X86NI 1 -#endif -#endif - -/* - * SSE2 intrinsics are available on x86 (32-bit and 64-bit) with - * GCC 4.4+, Clang 3.7+ and MSC 2005+. - */ -#ifndef BR_SSE2 -#if (BR_i386 || BR_amd64) && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005) -#define BR_SSE2 1 -#endif -#endif - -/* - * RDRAND intrinsics are available on x86 (32-bit and 64-bit) with - * GCC 4.6+, Clang 3.7+ and MSC 2012+. - */ -#ifndef BR_RDRAND -#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012) -#define BR_RDRAND 1 -#endif -#endif - -/* - * Determine type of OS for random number generation. Macro names and - * values are documented on: - * https://sourceforge.net/p/predef/wiki/OperatingSystems/ - * - * TODO: enrich the list of detected system. Also add detection for - * alternate system calls like getentropy(), which are usually - * preferable when available. - */ - -#ifndef BR_USE_URANDOM -#if defined _AIX \ - || defined __ANDROID__ \ - || defined __FreeBSD__ \ - || defined __NetBSD__ \ - || defined __OpenBSD__ \ - || defined __DragonFly__ \ - || defined __linux__ \ - || (defined __sun && (defined __SVR4 || defined __svr4__)) \ - || (defined __APPLE__ && defined __MACH__) -#define BR_USE_URANDOM 1 -#endif -#endif - -#ifndef BR_USE_WIN32_RAND -#if defined _WIN32 || defined _WIN64 -#define BR_USE_WIN32_RAND 1 -#endif -#endif - -/* - * POWER8 crypto support. We rely on compiler macros for the - * architecture, since we do not have a reliable, simple way to detect - * the required support at runtime (we could try running an opcode, and - * trapping the exception or signal on illegal instruction, but this - * induces some non-trivial OS dependencies that we would prefer to - * avoid if possible). - */ -#ifndef BR_POWER8 -#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__) -#define BR_POWER8 1 -#endif -#endif - -/* - * Detect endinanness on POWER8. - */ -#if BR_POWER8 -#if defined BR_POWER8_LE -#undef BR_POWER8_BE -#if BR_POWER8_LE -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_BE 1 -#endif -#elif defined BR_POWER8_BE -#undef BR_POWER8_LE -#if BR_POWER8_BE -#define BR_POWER8_LE 0 -#else -#define BR_POWER8_LE 1 -#endif -#else -#if __LITTLE_ENDIAN__ -#define BR_POWER8_LE 1 -#define BR_POWER8_BE 0 -#else -#define BR_POWER8_LE 0 -#define BR_POWER8_BE 1 -#endif -#endif -#endif - -/* - * Detect support for 128-bit integers. - */ -#if !defined BR_INT128 && !defined BR_UMUL128 -#ifdef __SIZEOF_INT128__ -#define BR_INT128 1 -#elif _M_X64 -#define BR_UMUL128 1 -#endif -#endif - -/* - * Detect support for unaligned accesses with known endianness. - * - * x86 (both 32-bit and 64-bit) is little-endian and allows unaligned - * accesses. - * - * POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and - * later also allow unaligned accesses when little-endian. - */ -#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED - -#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 -#define BR_LE_UNALIGNED 1 -#elif BR_POWER8_BE -#define BR_BE_UNALIGNED 1 -#elif BR_POWER8_LE -#define BR_LE_UNALIGNED 1 -#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \ - && __BIG_ENDIAN__ -#define BR_BE_UNALIGNED 1 -#endif - -#endif - -/* - * Detect support for an OS-provided time source. - */ - -#ifndef BR_USE_UNIX_TIME -#if defined __unix__ || defined __linux__ \ - || defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \ - || (defined __APPLE__ && defined __MACH__) -#define BR_USE_UNIX_TIME 1 -#endif -#endif - -#ifndef BR_USE_WIN32_TIME -#if defined _WIN32 || defined _WIN64 -#define BR_USE_WIN32_TIME 1 -#endif -#endif - -/* ==================================================================== */ -/* - * Encoding/decoding functions. - * - * 32-bit and 64-bit decoding, both little-endian and big-endian, is - * implemented with the inline functions below. - * - * When allowed by some compile-time options (autodetected or provided), - * optimised code is used, to perform direct memory access when the - * underlying architecture supports it, both for endianness and - * alignment. This, however, may trigger strict aliasing issues; the - * code below uses unions to perform (supposedly) safe type punning. - * Since the C aliasing rules are relatively complex and were amended, - * or at least re-explained with different phrasing, in all successive - * versions of the C standard, it is always a bit risky to bet that any - * specific version of a C compiler got it right, for some notion of - * "right". - */ - -typedef union { - uint16_t u; - unsigned char b[sizeof(uint16_t)]; -} br_union_u16; - -typedef union { - uint32_t u; - unsigned char b[sizeof(uint32_t)]; -} br_union_u32; - -typedef union { - uint64_t u; - unsigned char b[sizeof(uint64_t)]; -} br_union_u64; - -static inline void -br_enc16le(void *dst, unsigned x) -{ -#if BR_LE_UNALIGNED - ((br_union_u16 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - buf[0] = (unsigned char)x; - buf[1] = (unsigned char)(x >> 8); -#endif -} - -static inline void -br_enc16be(void *dst, unsigned x) -{ -#if BR_BE_UNALIGNED - ((br_union_u16 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - buf[0] = (unsigned char)(x >> 8); - buf[1] = (unsigned char)x; -#endif -} - -static inline unsigned -br_dec16le(const void *src) -{ -#if BR_LE_UNALIGNED - return ((const br_union_u16 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return (unsigned)buf[0] | ((unsigned)buf[1] << 8); -#endif -} - -static inline unsigned -br_dec16be(const void *src) -{ -#if BR_BE_UNALIGNED - return ((const br_union_u16 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return ((unsigned)buf[0] << 8) | (unsigned)buf[1]; -#endif -} - -static inline void -br_enc32le(void *dst, uint32_t x) -{ -#if BR_LE_UNALIGNED - ((br_union_u32 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - buf[0] = (unsigned char)x; - buf[1] = (unsigned char)(x >> 8); - buf[2] = (unsigned char)(x >> 16); - buf[3] = (unsigned char)(x >> 24); -#endif -} - -static inline void -br_enc32be(void *dst, uint32_t x) -{ -#if BR_BE_UNALIGNED - ((br_union_u32 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - buf[0] = (unsigned char)(x >> 24); - buf[1] = (unsigned char)(x >> 16); - buf[2] = (unsigned char)(x >> 8); - buf[3] = (unsigned char)x; -#endif -} - -static inline uint32_t -br_dec32le(const void *src) -{ -#if BR_LE_UNALIGNED - return ((const br_union_u32 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return (uint32_t)buf[0] - | ((uint32_t)buf[1] << 8) - | ((uint32_t)buf[2] << 16) - | ((uint32_t)buf[3] << 24); -#endif -} - -static inline uint32_t -br_dec32be(const void *src) -{ -#if BR_BE_UNALIGNED - return ((const br_union_u32 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return ((uint32_t)buf[0] << 24) - | ((uint32_t)buf[1] << 16) - | ((uint32_t)buf[2] << 8) - | (uint32_t)buf[3]; -#endif -} - -static inline void -br_enc64le(void *dst, uint64_t x) -{ -#if BR_LE_UNALIGNED - ((br_union_u64 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - br_enc32le(buf, (uint32_t)x); - br_enc32le(buf + 4, (uint32_t)(x >> 32)); -#endif -} - -static inline void -br_enc64be(void *dst, uint64_t x) -{ -#if BR_BE_UNALIGNED - ((br_union_u64 *)dst)->u = x; -#else - unsigned char *buf; - - buf = dst; - br_enc32be(buf, (uint32_t)(x >> 32)); - br_enc32be(buf + 4, (uint32_t)x); -#endif -} - -static inline uint64_t -br_dec64le(const void *src) -{ -#if BR_LE_UNALIGNED - return ((const br_union_u64 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return (uint64_t)br_dec32le(buf) - | ((uint64_t)br_dec32le(buf + 4) << 32); -#endif -} - -static inline uint64_t -br_dec64be(const void *src) -{ -#if BR_BE_UNALIGNED - return ((const br_union_u64 *)src)->u; -#else - const unsigned char *buf; - - buf = src; - return ((uint64_t)br_dec32be(buf) << 32) - | (uint64_t)br_dec32be(buf + 4); -#endif -} - -/* - * Range decoding and encoding (for several successive values). - */ -void br_range_dec16le(uint16_t *v, size_t num, const void *src); -void br_range_dec16be(uint16_t *v, size_t num, const void *src); -void br_range_enc16le(void *dst, const uint16_t *v, size_t num); -void br_range_enc16be(void *dst, const uint16_t *v, size_t num); - -void br_range_dec32le(uint32_t *v, size_t num, const void *src); -void br_range_dec32be(uint32_t *v, size_t num, const void *src); -void br_range_enc32le(void *dst, const uint32_t *v, size_t num); -void br_range_enc32be(void *dst, const uint32_t *v, size_t num); - -void br_range_dec64le(uint64_t *v, size_t num, const void *src); -void br_range_dec64be(uint64_t *v, size_t num, const void *src); -void br_range_enc64le(void *dst, const uint64_t *v, size_t num); -void br_range_enc64be(void *dst, const uint64_t *v, size_t num); - -/* - * Byte-swap a 32-bit integer. - */ -static inline uint32_t -br_swap32(uint32_t x) -{ - x = ((x & (uint32_t)0x00FF00FF) << 8) - | ((x >> 8) & (uint32_t)0x00FF00FF); - return (x << 16) | (x >> 16); -} - -/* ==================================================================== */ -/* - * Support code for hash functions. - */ - -/* - * IV for MD5, SHA-1, SHA-224 and SHA-256. - */ -extern const uint32_t br_md5_IV[]; -extern const uint32_t br_sha1_IV[]; -extern const uint32_t br_sha224_IV[]; -extern const uint32_t br_sha256_IV[]; - -/* - * Round functions for MD5, SHA-1, SHA-224 and SHA-256 (SHA-224 and - * SHA-256 use the same round function). - */ -void br_md5_round(const unsigned char *buf, uint32_t *val); -void br_sha1_round(const unsigned char *buf, uint32_t *val); -void br_sha2small_round(const unsigned char *buf, uint32_t *val); - -/* - * The core function for the TLS PRF. It computes - * P_hash(secret, label + seed), and XORs the result into the dst buffer. - */ -void br_tls_phash(void *dst, size_t len, - const br_hash_class *dig, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed); - -/* - * Copy all configured hash implementations from a multihash context - * to another. - */ -static inline void -br_multihash_copyimpl(br_multihash_context *dst, - const br_multihash_context *src) -{ - memcpy((void *)dst->impl, src->impl, sizeof src->impl); -} - -/* ==================================================================== */ -/* - * Constant-time primitives. These functions manipulate 32-bit values in - * order to provide constant-time comparisons and multiplexers. - * - * Boolean values (the "ctl" bits) MUST have value 0 or 1. - * - * Implementation notes: - * ===================== - * - * The uintN_t types are unsigned and with width exactly N bits; the C - * standard guarantees that computations are performed modulo 2^N, and - * there can be no overflow. Negation (unary '-') works on unsigned types - * as well. - * - * The intN_t types are guaranteed to have width exactly N bits, with no - * padding bit, and using two's complement representation. Casting - * intN_t to uintN_t really is conversion modulo 2^N. Beware that intN_t - * types, being signed, trigger implementation-defined behaviour on - * overflow (including raising some signal): with GCC, while modular - * arithmetic is usually applied, the optimizer may assume that - * overflows don't occur (unless the -fwrapv command-line option is - * added); Clang has the additional -ftrapv option to explicitly trap on - * integer overflow or underflow. - */ - -/* - * Negate a boolean. - */ -static inline uint32_t -NOT(uint32_t ctl) -{ - return ctl ^ 1; -} - -/* - * Multiplexer: returns x if ctl == 1, y if ctl == 0. - */ -static inline uint32_t -MUX(uint32_t ctl, uint32_t x, uint32_t y) -{ - return y ^ (-ctl & (x ^ y)); -} - -/* - * Equality check: returns 1 if x == y, 0 otherwise. - */ -static inline uint32_t -EQ(uint32_t x, uint32_t y) -{ - uint32_t q; - - q = x ^ y; - return NOT((q | -q) >> 31); -} - -/* - * Inequality check: returns 1 if x != y, 0 otherwise. - */ -static inline uint32_t -NEQ(uint32_t x, uint32_t y) -{ - uint32_t q; - - q = x ^ y; - return (q | -q) >> 31; -} - -/* - * Comparison: returns 1 if x > y, 0 otherwise. - */ -static inline uint32_t -GT(uint32_t x, uint32_t y) -{ - /* - * If both x < 2^31 and x < 2^31, then y-x will have its high - * bit set if x > y, cleared otherwise. - * - * If either x >= 2^31 or y >= 2^31 (but not both), then the - * result is the high bit of x. - * - * If both x >= 2^31 and y >= 2^31, then we can virtually - * subtract 2^31 from both, and we are back to the first case. - * Since (y-2^31)-(x-2^31) = y-x, the subtraction is already - * fine. - */ - uint32_t z; - - z = y - x; - return (z ^ ((x ^ y) & (x ^ z))) >> 31; -} - -/* - * Other comparisons (greater-or-equal, lower-than, lower-or-equal). - */ -#define GE(x, y) NOT(GT(y, x)) -#define LT(x, y) GT(y, x) -#define LE(x, y) NOT(GT(x, y)) - -/* - * General comparison: returned value is -1, 0 or 1, depending on - * whether x is lower than, equal to, or greater than y. - */ -static inline int32_t -CMP(uint32_t x, uint32_t y) -{ - return (int32_t)GT(x, y) | -(int32_t)GT(y, x); -} - -/* - * Returns 1 if x == 0, 0 otherwise. Take care that the operand is signed. - */ -static inline uint32_t -EQ0(int32_t x) -{ - uint32_t q; - - q = (uint32_t)x; - return ~(q | -q) >> 31; -} - -/* - * Returns 1 if x > 0, 0 otherwise. Take care that the operand is signed. - */ -static inline uint32_t -GT0(int32_t x) -{ - /* - * High bit of -x is 0 if x == 0, but 1 if x > 0. - */ - uint32_t q; - - q = (uint32_t)x; - return (~q & -q) >> 31; -} - -/* - * Returns 1 if x >= 0, 0 otherwise. Take care that the operand is signed. - */ -static inline uint32_t -GE0(int32_t x) -{ - return ~(uint32_t)x >> 31; -} - -/* - * Returns 1 if x < 0, 0 otherwise. Take care that the operand is signed. - */ -static inline uint32_t -LT0(int32_t x) -{ - return (uint32_t)x >> 31; -} - -/* - * Returns 1 if x <= 0, 0 otherwise. Take care that the operand is signed. - */ -static inline uint32_t -LE0(int32_t x) -{ - uint32_t q; - - /* - * ~-x has its high bit set if and only if -x is nonnegative (as - * a signed int), i.e. x is in the -(2^31-1) to 0 range. We must - * do an OR with x itself to account for x = -2^31. - */ - q = (uint32_t)x; - return (q | ~-q) >> 31; -} - -/* - * Conditional copy: src[] is copied into dst[] if and only if ctl is 1. - * dst[] and src[] may overlap completely (but not partially). - */ -void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len); - -#define CCOPY br_ccopy - -/* - * Compute the bit length of a 32-bit integer. Returned value is between 0 - * and 32 (inclusive). - */ -static inline uint32_t -BIT_LENGTH(uint32_t x) -{ - uint32_t k, c; - - k = NEQ(x, 0); - c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4; - c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3; - c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2; - c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1; - k += GT(x, 0x0001); - return k; -} - -/* - * Compute the minimum of x and y. - */ -static inline uint32_t -MIN(uint32_t x, uint32_t y) -{ - return MUX(GT(x, y), y, x); -} - -/* - * Compute the maximum of x and y. - */ -static inline uint32_t -MAX(uint32_t x, uint32_t y) -{ - return MUX(GT(x, y), x, y); -} - -/* - * Multiply two 32-bit integers, with a 64-bit result. This default - * implementation assumes that the basic multiplication operator - * yields constant-time code. - */ -#define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y)) - -#if BR_CT_MUL31 - -/* - * Alternate implementation of MUL31, that will be constant-time on some - * (old) platforms where the default MUL31 is not. Unfortunately, it is - * also substantially slower, and yields larger code, on more modern - * platforms, which is why it is deactivated by default. - * - * MUL31_lo() must do some extra work because on some platforms, the - * _signed_ multiplication may return early if the top bits are 1. - * Simply truncating (casting) the output of MUL31() would not be - * sufficient, because the compiler may notice that we keep only the low - * word, and then replace automatically the unsigned multiplication with - * a signed multiplication opcode. - */ -#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \ - * (uint64_t)((y) | (uint32_t)0x80000000) \ - - ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \ - - ((uint64_t)1 << 62)) -static inline uint32_t -MUL31_lo(uint32_t x, uint32_t y) -{ - uint32_t xl, xh; - uint32_t yl, yh; - - xl = (x & 0xFFFF) | (uint32_t)0x80000000; - xh = (x >> 16) | (uint32_t)0x80000000; - yl = (y & 0xFFFF) | (uint32_t)0x80000000; - yh = (y >> 16) | (uint32_t)0x80000000; - return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF; -} - -#else - -/* - * Multiply two 31-bit integers, with a 62-bit result. This default - * implementation assumes that the basic multiplication operator - * yields constant-time code. - * The MUL31_lo() macro returns only the low 31 bits of the product. - */ -#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y)) -#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF) - -#endif - -/* - * Multiply two words together; the sum of the lengths of the two - * operands must not exceed 31 (for instance, one operand may use 16 - * bits if the other fits on 15). If BR_CT_MUL15 is non-zero, then the - * macro will contain some extra operations that help in making the - * operation constant-time on some platforms, where the basic 32-bit - * multiplication is not constant-time. - */ -#if BR_CT_MUL15 -#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \ - * ((uint32_t)(y) | (uint32_t)0x80000000) \ - & (uint32_t)0x7FFFFFFF) -#else -#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y)) -#endif - -/* - * Arithmetic right shift (sign bit is copied). What happens when - * right-shifting a negative value is _implementation-defined_, so it - * does not trigger undefined behaviour, but it is still up to each - * compiler to define (and document) what it does. Most/all compilers - * will do an arithmetic shift, the sign bit being used to fill the - * holes; this is a native operation on the underlying CPU, and it would - * make little sense for the compiler to do otherwise. GCC explicitly - * documents that it follows that convention. - * - * Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an - * alternate version will be used, that does not rely on such - * implementation-defined behaviour. Unfortunately, it is also slower - * and yields bigger code, which is why it is deactivated by default. - */ -#if BR_NO_ARITH_SHIFT -#define ARSH(x, n) (((uint32_t)(x) >> (n)) \ - | ((-((uint32_t)(x) >> 31)) << (32 - (n)))) -#else -#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) -#endif - -/* - * Constant-time division. The dividend hi:lo is divided by the - * divisor d; the quotient is returned and the remainder is written - * in *r. If hi == d, then the quotient does not fit on 32 bits; - * returned value is thus truncated. If hi > d, returned values are - * indeterminate. - */ -uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r); - -/* - * Wrapper for br_divrem(); the remainder is returned, and the quotient - * is discarded. - */ -static inline uint32_t -br_rem(uint32_t hi, uint32_t lo, uint32_t d) -{ - uint32_t r; - - br_divrem(hi, lo, d, &r); - return r; -} - -/* - * Wrapper for br_divrem(); the quotient is returned, and the remainder - * is discarded. - */ -static inline uint32_t -br_div(uint32_t hi, uint32_t lo, uint32_t d) -{ - uint32_t r; - - return br_divrem(hi, lo, d, &r); -} - -/* ==================================================================== */ - -/* - * Integers 'i32' - * -------------- - * - * The 'i32' functions implement computations on big integers using - * an internal representation as an array of 32-bit integers. For - * an array x[]: - * -- x[0] contains the "announced bit length" of the integer - * -- x[1], x[2]... contain the value in little-endian order (x[1] - * contains the least significant 32 bits) - * - * Multiplications rely on the elementary 32x32->64 multiplication. - * - * The announced bit length specifies the number of bits that are - * significant in the subsequent 32-bit words. Unused bits in the - * last (most significant) word are set to 0; subsequent words are - * uninitialized and need not exist at all. - * - * The execution time and memory access patterns of all computations - * depend on the announced bit length, but not on the actual word - * values. For modular integers, the announced bit length of any integer - * modulo n is equal to the actual bit length of n; thus, computations - * on modular integers are "constant-time" (only the modulus length may - * leak). - */ - -/* - * Compute the actual bit length of an integer. The argument x should - * point to the first (least significant) value word of the integer. - * The len 'xlen' contains the number of 32-bit words to access. - * - * CT: value or length of x does not leak. - */ -uint32_t br_i32_bit_length(uint32_t *x, size_t xlen); - -/* - * Decode an integer from its big-endian unsigned representation. The - * "true" bit length of the integer is computed, but all words of x[] - * corresponding to the full 'len' bytes of the source are set. - * - * CT: value or length of x does not leak. - */ -void br_i32_decode(uint32_t *x, const void *src, size_t len); - -/* - * Decode an integer from its big-endian unsigned representation. The - * integer MUST be lower than m[]; the announced bit length written in - * x[] will be equal to that of m[]. All 'len' bytes from the source are - * read. - * - * Returned value is 1 if the decode value fits within the modulus, 0 - * otherwise. In the latter case, the x[] buffer will be set to 0 (but - * still with the announced bit length of m[]). - * - * CT: value or length of x does not leak. Memory access pattern depends - * only of 'len' and the announced bit length of m. Whether x fits or - * not does not leak either. - */ -uint32_t br_i32_decode_mod(uint32_t *x, - const void *src, size_t len, const uint32_t *m); - -/* - * Reduce an integer (a[]) modulo another (m[]). The result is written - * in x[] and its announced bit length is set to be equal to that of m[]. - * - * x[] MUST be distinct from a[] and m[]. - * - * CT: only announced bit lengths leak, not values of x, a or m. - */ -void br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m); - -/* - * Decode an integer from its big-endian unsigned representation, and - * reduce it modulo the provided modulus m[]. The announced bit length - * of the result is set to be equal to that of the modulus. - * - * x[] MUST be distinct from m[]. - */ -void br_i32_decode_reduce(uint32_t *x, - const void *src, size_t len, const uint32_t *m); - -/* - * Encode an integer into its big-endian unsigned representation. The - * output length in bytes is provided (parameter 'len'); if the length - * is too short then the integer is appropriately truncated; if it is - * too long then the extra bytes are set to 0. - */ -void br_i32_encode(void *dst, size_t len, const uint32_t *x); - -/* - * Multiply x[] by 2^32 and then add integer z, modulo m[]. This - * function assumes that x[] and m[] have the same announced bit - * length, and the announced bit length of m[] matches its true - * bit length. - * - * x[] and m[] MUST be distinct arrays. - * - * CT: only the common announced bit length of x and m leaks, not - * the values of x, z or m. - */ -void br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m); - -/* - * Extract one word from an integer. The offset is counted in bits. - * The word MUST entirely fit within the word elements corresponding - * to the announced bit length of a[]. - */ -static inline uint32_t -br_i32_word(const uint32_t *a, uint32_t off) -{ - size_t u; - unsigned j; - - u = (size_t)(off >> 5) + 1; - j = (unsigned)off & 31; - if (j == 0) { - return a[u]; - } else { - return (a[u] >> j) | (a[u + 1] << (32 - j)); - } -} - -/* - * Test whether an integer is zero. - */ -uint32_t br_i32_iszero(const uint32_t *x); - -/* - * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[] - * is unmodified, but the carry is still computed and returned. The - * arrays a[] and b[] MUST have the same announced bit length. - * - * a[] and b[] MAY be the same array, but partial overlap is not allowed. - */ -uint32_t br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl); - -/* - * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0, - * then a[] is unmodified, but the carry is still computed and returned. - * The arrays a[] and b[] MUST have the same announced bit length. - * - * a[] and b[] MAY be the same array, but partial overlap is not allowed. - */ -uint32_t br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl); - -/* - * Compute d+a*b, result in d. The initial announced bit length of d[] - * MUST match that of a[]. The d[] array MUST be large enough to - * accommodate the full result, plus (possibly) an extra word. The - * resulting announced bit length of d[] will be the sum of the announced - * bit lengths of a[] and b[] (therefore, it may be larger than the actual - * bit length of the numerical result). - * - * a[] and b[] may be the same array. d[] must be disjoint from both a[] - * and b[]. - */ -void br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b); - -/* - * Zeroize an integer. The announced bit length is set to the provided - * value, and the corresponding words are set to 0. - */ -static inline void -br_i32_zero(uint32_t *x, uint32_t bit_len) -{ - *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); -} - -/* - * Compute -(1/x) mod 2^32. If x is even, then this function returns 0. - */ -uint32_t br_i32_ninv32(uint32_t x); - -/* - * Convert a modular integer to Montgomery representation. The integer x[] - * MUST be lower than m[], but with the same announced bit length. - */ -void br_i32_to_monty(uint32_t *x, const uint32_t *m); - -/* - * Convert a modular integer back from Montgomery representation. The - * integer x[] MUST be lower than m[], but with the same announced bit - * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is - * the least significant value word of m[] (this works only if m[] is - * an odd integer). - */ -void br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i); - -/* - * Compute a modular Montgomery multiplication. d[] is filled with the - * value of x*y/R modulo m[] (where R is the Montgomery factor). The - * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be - * numerically lower than m[]. x[] and y[] MAY be the same array. The - * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least - * significant value word of m[] (this works only if m[] is an odd - * integer). - */ -void br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, - const uint32_t *m, uint32_t m0i); - -/* - * Compute a modular exponentiation. x[] MUST be an integer modulo m[] - * (same announced bit length, lower value). m[] MUST be odd. The - * exponent is in big-endian unsigned notation, over 'elen' bytes. The - * "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least - * significant value word of m[] (this works only if m[] is an odd - * integer). The t1[] and t2[] parameters must be temporary arrays, - * each large enough to accommodate an integer with the same size as m[]. - */ -void br_i32_modpow(uint32_t *x, const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2); - -/* ==================================================================== */ - -/* - * Integers 'i31' - * -------------- - * - * The 'i31' functions implement computations on big integers using - * an internal representation as an array of 32-bit integers. For - * an array x[]: - * -- x[0] encodes the array length and the "announced bit length" - * of the integer: namely, if the announced bit length is k, - * then x[0] = ((k / 31) << 5) + (k % 31). - * -- x[1], x[2]... contain the value in little-endian order, 31 - * bits per word (x[1] contains the least significant 31 bits). - * The upper bit of each word is 0. - * - * Multiplications rely on the elementary 32x32->64 multiplication. - * - * The announced bit length specifies the number of bits that are - * significant in the subsequent 32-bit words. Unused bits in the - * last (most significant) word are set to 0; subsequent words are - * uninitialized and need not exist at all. - * - * The execution time and memory access patterns of all computations - * depend on the announced bit length, but not on the actual word - * values. For modular integers, the announced bit length of any integer - * modulo n is equal to the actual bit length of n; thus, computations - * on modular integers are "constant-time" (only the modulus length may - * leak). - */ - -/* - * Test whether an integer is zero. - */ -uint32_t br_i31_iszero(const uint32_t *x); - -/* - * Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[] - * is unmodified, but the carry is still computed and returned. The - * arrays a[] and b[] MUST have the same announced bit length. - * - * a[] and b[] MAY be the same array, but partial overlap is not allowed. - */ -uint32_t br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl); - -/* - * Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0, - * then a[] is unmodified, but the carry is still computed and returned. - * The arrays a[] and b[] MUST have the same announced bit length. - * - * a[] and b[] MAY be the same array, but partial overlap is not allowed. - */ -uint32_t br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl); - -/* - * Compute the ENCODED actual bit length of an integer. The argument x - * should point to the first (least significant) value word of the - * integer. The len 'xlen' contains the number of 32-bit words to - * access. The upper bit of each value word MUST be 0. - * Returned value is ((k / 31) << 5) + (k % 31) if the bit length is k. - * - * CT: value or length of x does not leak. - */ -uint32_t br_i31_bit_length(uint32_t *x, size_t xlen); - -/* - * Decode an integer from its big-endian unsigned representation. The - * "true" bit length of the integer is computed and set in the encoded - * announced bit length (x[0]), but all words of x[] corresponding to - * the full 'len' bytes of the source are set. - * - * CT: value or length of x does not leak. - */ -void br_i31_decode(uint32_t *x, const void *src, size_t len); - -/* - * Decode an integer from its big-endian unsigned representation. The - * integer MUST be lower than m[]; the (encoded) announced bit length - * written in x[] will be equal to that of m[]. All 'len' bytes from the - * source are read. - * - * Returned value is 1 if the decode value fits within the modulus, 0 - * otherwise. In the latter case, the x[] buffer will be set to 0 (but - * still with the announced bit length of m[]). - * - * CT: value or length of x does not leak. Memory access pattern depends - * only of 'len' and the announced bit length of m. Whether x fits or - * not does not leak either. - */ -uint32_t br_i31_decode_mod(uint32_t *x, - const void *src, size_t len, const uint32_t *m); - -/* - * Zeroize an integer. The announced bit length is set to the provided - * value, and the corresponding words are set to 0. The ENCODED bit length - * is expected here. - */ -static inline void -br_i31_zero(uint32_t *x, uint32_t bit_len) -{ - *x ++ = bit_len; - memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x); -} - -/* - * Right-shift an integer. The shift amount must be lower than 31 - * bits. - */ -void br_i31_rshift(uint32_t *x, int count); - -/* - * Reduce an integer (a[]) modulo another (m[]). The result is written - * in x[] and its announced bit length is set to be equal to that of m[]. - * - * x[] MUST be distinct from a[] and m[]. - * - * CT: only announced bit lengths leak, not values of x, a or m. - */ -void br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m); - -/* - * Decode an integer from its big-endian unsigned representation, and - * reduce it modulo the provided modulus m[]. The announced bit length - * of the result is set to be equal to that of the modulus. - * - * x[] MUST be distinct from m[]. - */ -void br_i31_decode_reduce(uint32_t *x, - const void *src, size_t len, const uint32_t *m); - -/* - * Multiply x[] by 2^31 and then add integer z, modulo m[]. This - * function assumes that x[] and m[] have the same announced bit - * length, the announced bit length of m[] matches its true - * bit length. - * - * x[] and m[] MUST be distinct arrays. z MUST fit in 31 bits (upper - * bit set to 0). - * - * CT: only the common announced bit length of x and m leaks, not - * the values of x, z or m. - */ -void br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m); - -/* - * Encode an integer into its big-endian unsigned representation. The - * output length in bytes is provided (parameter 'len'); if the length - * is too short then the integer is appropriately truncated; if it is - * too long then the extra bytes are set to 0. - */ -void br_i31_encode(void *dst, size_t len, const uint32_t *x); - -/* - * Compute -(1/x) mod 2^31. If x is even, then this function returns 0. - */ -uint32_t br_i31_ninv31(uint32_t x); - -/* - * Compute a modular Montgomery multiplication. d[] is filled with the - * value of x*y/R modulo m[] (where R is the Montgomery factor). The - * array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be - * numerically lower than m[]. x[] and y[] MAY be the same array. The - * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least - * significant value word of m[] (this works only if m[] is an odd - * integer). - */ -void br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y, - const uint32_t *m, uint32_t m0i); - -/* - * Convert a modular integer to Montgomery representation. The integer x[] - * MUST be lower than m[], but with the same announced bit length. - */ -void br_i31_to_monty(uint32_t *x, const uint32_t *m); - -/* - * Convert a modular integer back from Montgomery representation. The - * integer x[] MUST be lower than m[], but with the same announced bit - * length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is - * the least significant value word of m[] (this works only if m[] is - * an odd integer). - */ -void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i); - -/* - * Compute a modular exponentiation. x[] MUST be an integer modulo m[] - * (same announced bit length, lower value). m[] MUST be odd. The - * exponent is in big-endian unsigned notation, over 'elen' bytes. The - * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least - * significant value word of m[] (this works only if m[] is an odd - * integer). The t1[] and t2[] parameters must be temporary arrays, - * each large enough to accommodate an integer with the same size as m[]. - */ -void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2); - -/* - * Compute a modular exponentiation. x[] MUST be an integer modulo m[] - * (same announced bit length, lower value). m[] MUST be odd. The - * exponent is in big-endian unsigned notation, over 'elen' bytes. The - * "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least - * significant value word of m[] (this works only if m[] is an odd - * integer). The tmp[] array is used for temporaries, and has size - * 'twlen' words; it must be large enough to accommodate at least two - * temporary values with the same size as m[] (including the leading - * "bit length" word). If there is room for more temporaries, then this - * function may use the extra room for window-based optimisation, - * resulting in faster computations. - * - * Returned value is 1 on success, 0 on error. An error is reported if - * the provided tmp[] array is too short. - */ -uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); - -/* - * Compute d+a*b, result in d. The initial announced bit length of d[] - * MUST match that of a[]. The d[] array MUST be large enough to - * accommodate the full result, plus (possibly) an extra word. The - * resulting announced bit length of d[] will be the sum of the announced - * bit lengths of a[] and b[] (therefore, it may be larger than the actual - * bit length of the numerical result). - * - * a[] and b[] may be the same array. d[] must be disjoint from both a[] - * and b[]. - */ -void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b); - -/* - * Compute x/y mod m, result in x. Values x and y must be between 0 and - * m-1, and have the same announced bit length as m. Modulus m must be - * odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't' - * must point to a temporary area that can hold at least three integers - * of the size of m. - * - * m may not overlap x and y. x and y may overlap each other (this can - * be useful to test whether a value is invertible modulo m). t must be - * disjoint from all other arrays. - * - * Returned value is 1 on success, 0 otherwise. Success is attained if - * y is invertible modulo m. - */ -uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y, - const uint32_t *m, uint32_t m0i, uint32_t *t); - -/* ==================================================================== */ - -/* - * FIXME: document "i15" functions. - */ - -static inline void -br_i15_zero(uint16_t *x, uint16_t bit_len) -{ - *x ++ = bit_len; - memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); -} - -uint32_t br_i15_iszero(const uint16_t *x); - -uint16_t br_i15_ninv15(uint16_t x); - -uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl); - -uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl); - -void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m); - -void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, - const uint16_t *m, uint16_t m0i); - -void br_i15_to_monty(uint16_t *x, const uint16_t *m); - -void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen, - const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2); - -uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen, - const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen); - -void br_i15_encode(void *dst, size_t len, const uint16_t *x); - -uint32_t br_i15_decode_mod(uint16_t *x, - const void *src, size_t len, const uint16_t *m); - -void br_i15_rshift(uint16_t *x, int count); - -uint32_t br_i15_bit_length(uint16_t *x, size_t xlen); - -void br_i15_decode(uint16_t *x, const void *src, size_t len); - -void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i); - -void br_i15_decode_reduce(uint16_t *x, - const void *src, size_t len, const uint16_t *m); - -void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m); - -void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b); - -uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y, - const uint16_t *m, uint16_t m0i, uint16_t *t); - -/* - * Variant of br_i31_modpow_opt() that internally uses 64x64->128 - * multiplications. It expects the same parameters as br_i31_modpow_opt(), - * except that the temporaries should be 64-bit integers, not 32-bit - * integers. - */ -uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen, - const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen); - -/* - * Type for a function with the same API as br_i31_modpow_opt() (some - * implementations of this type may have stricter alignment requirements - * on the temporaries). - */ -typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x, - const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); - -/* - * Wrapper for br_i62_modpow_opt() that uses the same type as - * br_i31_modpow_opt(); however, it requires its 'tmp' argument to the - * 64-bit aligned. - */ -uint32_t br_i62_modpow_opt_as_i31(uint32_t *x, - const unsigned char *e, size_t elen, - const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen); - -/* ==================================================================== */ - -static inline size_t -br_digest_size(const br_hash_class *digest_class) -{ - return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF) - & BR_HASHDESC_OUT_MASK; -} - -/* - * Get the output size (in bytes) of a hash function. - */ -size_t br_digest_size_by_ID(int digest_id); - -/* - * Get the OID (encoded OBJECT IDENTIFIER value, without tag and length) - * for a hash function. If digest_id is not a supported digest identifier - * (in particular if it is equal to 0, i.e. br_md5sha1_ID), then NULL is - * returned and *len is set to 0. - */ -const unsigned char *br_digest_OID(int digest_id, size_t *len); - -/* ==================================================================== */ -/* - * DES support functions. - */ - -/* - * Apply DES Initial Permutation. - */ -void br_des_do_IP(uint32_t *xl, uint32_t *xr); - -/* - * Apply DES Final Permutation (inverse of IP). - */ -void br_des_do_invIP(uint32_t *xl, uint32_t *xr); - -/* - * Key schedule unit: for a DES key (8 bytes), compute 16 subkeys. Each - * subkey is two 28-bit words represented as two 32-bit words; the PC-2 - * bit exctration is NOT applied. - */ -void br_des_keysched_unit(uint32_t *skey, const void *key); - -/* - * Reversal of 16 DES sub-keys (for decryption). - */ -void br_des_rev_skey(uint32_t *skey); - -/* - * DES/3DES key schedule for 'des_tab' (encryption direction). Returned - * value is the number of rounds. - */ -unsigned br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len); - -/* - * DES/3DES key schedule for 'des_ct' (encryption direction). Returned - * value is the number of rounds. - */ -unsigned br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len); - -/* - * DES/3DES subkey decompression (from the compressed bitsliced subkeys). - */ -void br_des_ct_skey_expand(uint32_t *sk_exp, - unsigned num_rounds, const uint32_t *skey); - -/* - * DES/3DES block encryption/decryption ('des_tab'). - */ -void br_des_tab_process_block(unsigned num_rounds, - const uint32_t *skey, void *block); - -/* - * DES/3DES block encryption/decryption ('des_ct'). - */ -void br_des_ct_process_block(unsigned num_rounds, - const uint32_t *skey, void *block); - -/* ==================================================================== */ -/* - * AES support functions. - */ - -/* - * The AES S-box (256-byte table). - */ -extern const unsigned char br_aes_S[]; - -/* - * AES key schedule. skey[] is filled with n+1 128-bit subkeys, where n - * is the number of rounds (10 to 14, depending on key size). The number - * of rounds is returned. If the key size is invalid (not 16, 24 or 32), - * then 0 is returned. - * - * This implementation uses a 256-byte table and is NOT constant-time. - */ -unsigned br_aes_keysched(uint32_t *skey, const void *key, size_t key_len); - -/* - * AES key schedule for decryption ('aes_big' implementation). - */ -unsigned br_aes_big_keysched_inv(uint32_t *skey, - const void *key, size_t key_len); - -/* - * AES block encryption with the 'aes_big' implementation (fast, but - * not constant-time). This function encrypts a single block "in place". - */ -void br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data); - -/* - * AES block decryption with the 'aes_big' implementation (fast, but - * not constant-time). This function decrypts a single block "in place". - */ -void br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data); - -/* - * AES block encryption with the 'aes_small' implementation (small, but - * slow and not constant-time). This function encrypts a single block - * "in place". - */ -void br_aes_small_encrypt(unsigned num_rounds, - const uint32_t *skey, void *data); - -/* - * AES block decryption with the 'aes_small' implementation (small, but - * slow and not constant-time). This function decrypts a single block - * "in place". - */ -void br_aes_small_decrypt(unsigned num_rounds, - const uint32_t *skey, void *data); - -/* - * The constant-time implementation is "bitsliced": the 128-bit state is - * split over eight 32-bit words q* in the following way: - * - * -- Input block consists in 16 bytes: - * a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33 - * In the terminology of FIPS 197, this is a 4x4 matrix which is read - * column by column. - * - * -- Each byte is split into eight bits which are distributed over the - * eight words, at the same rank. Thus, for a byte x at rank k, bit 0 - * (least significant) of x will be at rank k in q0 (if that bit is b, - * then it contributes "b << k" to the value of q0), bit 1 of x will be - * at rank k in q1, and so on. - * - * -- Ranks given to bits are in "row order" and are either all even, or - * all odd. Two independent AES states are thus interleaved, one using - * the even ranks, the other the odd ranks. Row order means: - * a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33 - * - * Converting input bytes from two AES blocks to bitslice representation - * is done in the following way: - * -- Decode first block into the four words q0 q2 q4 q6, in that order, - * using little-endian convention. - * -- Decode second block into the four words q1 q3 q5 q7, in that order, - * using little-endian convention. - * -- Call br_aes_ct_ortho(). - * - * Converting back to bytes is done by using the reverse operations. Note - * that br_aes_ct_ortho() is its own inverse. - */ - -/* - * Perform bytewise orthogonalization of eight 32-bit words. Bytes - * of q0..q7 are spread over all words: for a byte x that occurs - * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit - * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j. - * - * This operation is an involution. - */ -void br_aes_ct_ortho(uint32_t *q); - -/* - * The AES S-box, as a bitsliced constant-time version. The input array - * consists in eight 32-bit words; 32 S-box instances are computed in - * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant) - * are spread over the words 0 to 7, at the same rank. - */ -void br_aes_ct_bitslice_Sbox(uint32_t *q); - -/* - * Like br_aes_bitslice_Sbox(), but for the inverse S-box. - */ -void br_aes_ct_bitslice_invSbox(uint32_t *q); - -/* - * Compute AES encryption on bitsliced data. Since input is stored on - * eight 32-bit words, two block encryptions are actually performed - * in parallel. - */ -void br_aes_ct_bitslice_encrypt(unsigned num_rounds, - const uint32_t *skey, uint32_t *q); - -/* - * Compute AES decryption on bitsliced data. Since input is stored on - * eight 32-bit words, two block decryptions are actually performed - * in parallel. - */ -void br_aes_ct_bitslice_decrypt(unsigned num_rounds, - const uint32_t *skey, uint32_t *q); - -/* - * AES key schedule, constant-time version. skey[] is filled with n+1 - * 128-bit subkeys, where n is the number of rounds (10 to 14, depending - * on key size). The number of rounds is returned. If the key size is - * invalid (not 16, 24 or 32), then 0 is returned. - */ -unsigned br_aes_ct_keysched(uint32_t *comp_skey, - const void *key, size_t key_len); - -/* - * Expand AES subkeys as produced by br_aes_ct_keysched(), into - * a larger array suitable for br_aes_ct_bitslice_encrypt() and - * br_aes_ct_bitslice_decrypt(). - */ -void br_aes_ct_skey_expand(uint32_t *skey, - unsigned num_rounds, const uint32_t *comp_skey); - -/* - * For the ct64 implementation, the same bitslicing technique is used, - * but four instances are interleaved. First instance uses bits 0, 4, - * 8, 12,... of each word; second instance uses bits 1, 5, 9, 13,... - * and so on. - */ - -/* - * Perform bytewise orthogonalization of eight 64-bit words. Bytes - * of q0..q7 are spread over all words: for a byte x that occurs - * at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit - * of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j. - * - * This operation is an involution. - */ -void br_aes_ct64_ortho(uint64_t *q); - -/* - * Interleave bytes for an AES input block. If input bytes are - * denoted 0123456789ABCDEF, and have been decoded with little-endian - * convention (w[0] contains 0123, with '3' being most significant; - * w[1] contains 4567, and so on), then output word q0 will be - * set to 08192A3B (again little-endian convention) and q1 will - * be set to 4C5D6E7F. - */ -void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w); - -/* - * Perform the opposite of br_aes_ct64_interleave_in(). - */ -void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1); - -/* - * The AES S-box, as a bitsliced constant-time version. The input array - * consists in eight 64-bit words; 64 S-box instances are computed in - * parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant) - * are spread over the words 0 to 7, at the same rank. - */ -void br_aes_ct64_bitslice_Sbox(uint64_t *q); - -/* - * Like br_aes_bitslice_Sbox(), but for the inverse S-box. - */ -void br_aes_ct64_bitslice_invSbox(uint64_t *q); - -/* - * Compute AES encryption on bitsliced data. Since input is stored on - * eight 64-bit words, four block encryptions are actually performed - * in parallel. - */ -void br_aes_ct64_bitslice_encrypt(unsigned num_rounds, - const uint64_t *skey, uint64_t *q); - -/* - * Compute AES decryption on bitsliced data. Since input is stored on - * eight 64-bit words, four block decryptions are actually performed - * in parallel. - */ -void br_aes_ct64_bitslice_decrypt(unsigned num_rounds, - const uint64_t *skey, uint64_t *q); - -/* - * AES key schedule, constant-time version. skey[] is filled with n+1 - * 128-bit subkeys, where n is the number of rounds (10 to 14, depending - * on key size). The number of rounds is returned. If the key size is - * invalid (not 16, 24 or 32), then 0 is returned. - */ -unsigned br_aes_ct64_keysched(uint64_t *comp_skey, - const void *key, size_t key_len); - -/* - * Expand AES subkeys as produced by br_aes_ct64_keysched(), into - * a larger array suitable for br_aes_ct64_bitslice_encrypt() and - * br_aes_ct64_bitslice_decrypt(). - */ -void br_aes_ct64_skey_expand(uint64_t *skey, - unsigned num_rounds, const uint64_t *comp_skey); - -/* - * Test support for AES-NI opcodes. - */ -int br_aes_x86ni_supported(void); - -/* - * AES key schedule, using x86 AES-NI instructions. This yields the - * subkeys in the encryption direction. Number of rounds is returned. - * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. - */ -unsigned br_aes_x86ni_keysched_enc(unsigned char *skni, - const void *key, size_t len); - -/* - * AES key schedule, using x86 AES-NI instructions. This yields the - * subkeys in the decryption direction. Number of rounds is returned. - * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. - */ -unsigned br_aes_x86ni_keysched_dec(unsigned char *skni, - const void *key, size_t len); - -/* - * Test support for AES POWER8 opcodes. - */ -int br_aes_pwr8_supported(void); - -/* - * AES key schedule, using POWER8 instructions. This yields the - * subkeys in the encryption direction. Number of rounds is returned. - * Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned. - */ -unsigned br_aes_pwr8_keysched(unsigned char *skni, - const void *key, size_t len); - -/* ==================================================================== */ -/* - * RSA. - */ - -/* - * Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is - * the encoded hash function OID, or NULL. - */ -uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - uint32_t n_bitlen, unsigned char *x); - -/* - * Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded - * hash function OID, or NULL. The provided 'sig' value is _after_ the - * modular exponentiation, i.e. it should be the padded hash. On - * success, the hashed message is extracted. - */ -uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, - const unsigned char *hash_oid, size_t hash_len, - unsigned char *hash_out); - -/* - * Apply OAEP padding. Returned value is the actual padded string length, - * or zero on error. - */ -size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, const br_rsa_public_key *pk, - void *dst, size_t dst_nax_len, const void *src, size_t src_len); - -/* - * Unravel and check OAEP padding. If the padding is correct, then 1 is - * returned, '*len' is adjusted to the length of the message, and the - * data is moved to the start of the 'data' buffer. If the padding is - * incorrect, then 0 is returned and '*len' is untouched. Either way, - * the complete buffer contents are altered. - */ -uint32_t br_rsa_oaep_unpad(const br_hash_class *dig, - const void *label, size_t label_len, void *data, size_t *len); - -/* - * Compute MGF1 for a given seed, and XOR the output into the provided - * buffer. - */ -void br_mgf1_xor(void *data, size_t len, - const br_hash_class *dig, const void *seed, size_t seed_len); - -/* - * Inner function for RSA key generation; used by the "i31" and "i62" - * implementations. - */ -uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31); - -/* ==================================================================== */ -/* - * Elliptic curves. - */ - -/* - * Type for generic EC parameters: curve order (unsigned big-endian - * encoding) and encoded conventional generator. - */ -typedef struct { - int curve; - const unsigned char *order; - size_t order_len; - const unsigned char *generator; - size_t generator_len; -} br_ec_curve_def; - -extern const br_ec_curve_def br_secp256r1; -extern const br_ec_curve_def br_secp384r1; -extern const br_ec_curve_def br_secp521r1; - -/* - * For Curve25519, the advertised "order" really is 2^255-1, since the - * point multipliction function really works over arbitrary 255-bit - * scalars. This value is only meant as a hint for ECDH key generation; - * only ECDSA uses the exact curve order, and ECDSA is not used with - * that specific curve. - */ -extern const br_ec_curve_def br_curve25519; - -/* - * Decode some bytes as an i31 integer, with truncation (corresponding - * to the 'bits2int' operation in RFC 6979). The target ENCODED bit - * length is provided as last parameter. The resulting value will have - * this declared bit length, and consists the big-endian unsigned decoding - * of exactly that many bits in the source (capped at the source length). - */ -void br_ecdsa_i31_bits2int(uint32_t *x, - const void *src, size_t len, uint32_t ebitlen); - -/* - * Decode some bytes as an i15 integer, with truncation (corresponding - * to the 'bits2int' operation in RFC 6979). The target ENCODED bit - * length is provided as last parameter. The resulting value will have - * this declared bit length, and consists the big-endian unsigned decoding - * of exactly that many bits in the source (capped at the source length). - */ -void br_ecdsa_i15_bits2int(uint16_t *x, - const void *src, size_t len, uint32_t ebitlen); - -/* ==================================================================== */ -/* - * ASN.1 support functions. - */ - -/* - * A br_asn1_uint structure contains encoding information about an - * INTEGER nonnegative value: pointer to the integer contents (unsigned - * big-endian representation), length of the integer contents, - * and length of the encoded value. The data shall have minimal length: - * - If the integer value is zero, then 'len' must be zero. - * - If the integer value is not zero, then data[0] must be non-zero. - * - * Under these conditions, 'asn1len' is necessarily equal to either len - * or len+1. - */ -typedef struct { - const unsigned char *data; - size_t len; - size_t asn1len; -} br_asn1_uint; - -/* - * Given an encoded integer (unsigned big-endian, with possible leading - * bytes of value 0), returned the "prepared INTEGER" structure. - */ -br_asn1_uint br_asn1_uint_prepare(const void *xdata, size_t xlen); - -/* - * Encode an ASN.1 length. The length of the encoded length is returned. - * If 'dest' is NULL, then no encoding is performed, but the length of - * the encoded length is still computed and returned. - */ -size_t br_asn1_encode_length(void *dest, size_t len); - -/* - * Convenient macro for computing lengths of lengths. - */ -#define len_of_len(len) br_asn1_encode_length(NULL, len) - -/* - * Encode a (prepared) ASN.1 INTEGER. The encoded length is returned. - * If 'dest' is NULL, then no encoding is performed, but the length of - * the encoded integer is still computed and returned. - */ -size_t br_asn1_encode_uint(void *dest, br_asn1_uint pp); - -/* - * Get the OID that identifies an elliptic curve. Returned value is - * the DER-encoded OID, with the length (always one byte) but without - * the tag. Thus, the first byte of the returned buffer contains the - * number of subsequent bytes in the value. If the curve is not - * recognised, NULL is returned. - */ -const unsigned char *br_get_curve_OID(int curve); - -/* - * Inner function for EC private key encoding. This is equivalent to - * the API function br_encode_ec_raw_der(), except for an extra - * parameter: if 'include_curve_oid' is zero, then the curve OID is - * _not_ included in the output blob (this is for PKCS#8 support). - */ -size_t br_encode_ec_raw_der_inner(void *dest, - const br_ec_private_key *sk, const br_ec_public_key *pk, - int include_curve_oid); - -/* ==================================================================== */ -/* - * SSL/TLS support functions. - */ - -/* - * Record types. - */ -#define BR_SSL_CHANGE_CIPHER_SPEC 20 -#define BR_SSL_ALERT 21 -#define BR_SSL_HANDSHAKE 22 -#define BR_SSL_APPLICATION_DATA 23 - -/* - * Handshake message types. - */ -#define BR_SSL_HELLO_REQUEST 0 -#define BR_SSL_CLIENT_HELLO 1 -#define BR_SSL_SERVER_HELLO 2 -#define BR_SSL_CERTIFICATE 11 -#define BR_SSL_SERVER_KEY_EXCHANGE 12 -#define BR_SSL_CERTIFICATE_REQUEST 13 -#define BR_SSL_SERVER_HELLO_DONE 14 -#define BR_SSL_CERTIFICATE_VERIFY 15 -#define BR_SSL_CLIENT_KEY_EXCHANGE 16 -#define BR_SSL_FINISHED 20 - -/* - * Alert levels. - */ -#define BR_LEVEL_WARNING 1 -#define BR_LEVEL_FATAL 2 - -/* - * Low-level I/O state. - */ -#define BR_IO_FAILED 0 -#define BR_IO_IN 1 -#define BR_IO_OUT 2 -#define BR_IO_INOUT 3 - -/* - * Mark a SSL engine as failed. The provided error code is recorded if - * the engine was not already marked as failed. If 'err' is 0, then the - * engine is marked as closed (without error). - */ -void br_ssl_engine_fail(br_ssl_engine_context *cc, int err); - -/* - * Test whether the engine is closed (normally or as a failure). - */ -static inline int -br_ssl_engine_closed(const br_ssl_engine_context *cc) -{ - return cc->iomode == BR_IO_FAILED; -} - -/* - * Configure a new maximum fragment length. If possible, the maximum - * length for outgoing records is immediately adjusted (if there are - * not already too many buffered bytes for that). - */ -void br_ssl_engine_new_max_frag_len( - br_ssl_engine_context *rc, unsigned max_frag_len); - -/* - * Test whether the current incoming record has been fully received - * or not. This functions returns 0 only if a complete record header - * has been received, but some of the (possibly encrypted) payload - * has not yet been obtained. - */ -int br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc); - -/* - * Flush the current record (if not empty). This is meant to be called - * from the handshake processor only. - */ -void br_ssl_engine_flush_record(br_ssl_engine_context *cc); - -/* - * Test whether there is some accumulated payload to send. - */ -static inline int -br_ssl_engine_has_pld_to_send(const br_ssl_engine_context *rc) -{ - return rc->oxa != rc->oxb && rc->oxa != rc->oxc; -} - -/* - * Initialize RNG in engine. Returned value is 1 on success, 0 on error. - * This function will try to use the OS-provided RNG, if available. If - * there is no OS-provided RNG, or if it failed, and no entropy was - * injected by the caller, then a failure will be reported. On error, - * the context error code is set. - */ -int br_ssl_engine_init_rand(br_ssl_engine_context *cc); - -/* - * Reset the handshake-related parts of the engine. - */ -void br_ssl_engine_hs_reset(br_ssl_engine_context *cc, - void (*hsinit)(void *), void (*hsrun)(void *)); - -/* - * Get the PRF to use for this context, for the provided PRF hash - * function ID. - */ -br_tls_prf_impl br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id); - -/* - * Consume the provided pre-master secret and compute the corresponding - * master secret. The 'prf_id' is the ID of the hash function to use - * with the TLS 1.2 PRF (ignored if the version is TLS 1.0 or 1.1). - */ -void br_ssl_engine_compute_master(br_ssl_engine_context *cc, - int prf_id, const void *pms, size_t len); - -/* - * Switch to CBC decryption for incoming records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF (ignored if not TLS 1.2+) - * mac_id id of hash function for HMAC - * bc_impl block cipher implementation (CBC decryption) - * cipher_key_len block cipher key length (in bytes) - */ -void br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc, - int is_client, int prf_id, int mac_id, - const br_block_cbcdec_class *bc_impl, size_t cipher_key_len); - -/* - * Switch to CBC encryption for outgoing records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF (ignored if not TLS 1.2+) - * mac_id id of hash function for HMAC - * bc_impl block cipher implementation (CBC encryption) - * cipher_key_len block cipher key length (in bytes) - */ -void br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc, - int is_client, int prf_id, int mac_id, - const br_block_cbcenc_class *bc_impl, size_t cipher_key_len); - -/* - * Switch to GCM decryption for incoming records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - * bc_impl block cipher implementation (CTR) - * cipher_key_len block cipher key length (in bytes) - */ -void br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctr_class *bc_impl, size_t cipher_key_len); - -/* - * Switch to GCM encryption for outgoing records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - * bc_impl block cipher implementation (CTR) - * cipher_key_len block cipher key length (in bytes) - */ -void br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctr_class *bc_impl, size_t cipher_key_len); - -/* - * Switch to ChaCha20+Poly1305 decryption for incoming records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - */ -void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc, - int is_client, int prf_id); - -/* - * Switch to ChaCha20+Poly1305 encryption for outgoing records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - */ -void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc, - int is_client, int prf_id); - -/* - * Switch to CCM decryption for incoming records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - * bc_impl block cipher implementation (CTR+CBC) - * cipher_key_len block cipher key length (in bytes) - * tag_len tag length (in bytes) - */ -void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctrcbc_class *bc_impl, - size_t cipher_key_len, size_t tag_len); - -/* - * Switch to GCM encryption for outgoing records. - * cc the engine context - * is_client non-zero for a client, zero for a server - * prf_id id of hash function for PRF - * bc_impl block cipher implementation (CTR+CBC) - * cipher_key_len block cipher key length (in bytes) - * tag_len tag length (in bytes) - */ -void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctrcbc_class *bc_impl, - size_t cipher_key_len, size_t tag_len); - -/* - * Calls to T0-generated code. - */ -void br_ssl_hs_client_init_main(void *ctx); -void br_ssl_hs_client_run(void *ctx); -void br_ssl_hs_server_init_main(void *ctx); -void br_ssl_hs_server_run(void *ctx); - -/* - * Get the hash function to use for signatures, given a bit mask of - * supported hash functions. This implements a strict choice order - * (namely SHA-256, SHA-384, SHA-512, SHA-224, SHA-1). If the mask - * does not document support of any of these hash functions, then this - * functions returns 0. - */ -int br_ssl_choose_hash(unsigned bf); - -/* ==================================================================== */ - -/* - * PowerPC / POWER assembly stuff. The special BR_POWER_ASM_MACROS macro - * must be defined before including this file; this is done by source - * files that use some inline assembly for PowerPC / POWER machines. - */ - -#if BR_POWER_ASM_MACROS - -#define lxvw4x(xt, ra, rb) lxvw4x_(xt, ra, rb) -#define stxvw4x(xt, ra, rb) stxvw4x_(xt, ra, rb) - -#define bdnz(foo) bdnz_(foo) -#define bdz(foo) bdz_(foo) -#define beq(foo) beq_(foo) - -#define li(rx, value) li_(rx, value) -#define addi(rx, ra, imm) addi_(rx, ra, imm) -#define cmpldi(rx, imm) cmpldi_(rx, imm) -#define mtctr(rx) mtctr_(rx) -#define vspltb(vrt, vrb, uim) vspltb_(vrt, vrb, uim) -#define vspltw(vrt, vrb, uim) vspltw_(vrt, vrb, uim) -#define vspltisb(vrt, imm) vspltisb_(vrt, imm) -#define vspltisw(vrt, imm) vspltisw_(vrt, imm) -#define vrlw(vrt, vra, vrb) vrlw_(vrt, vra, vrb) -#define vsbox(vrt, vra) vsbox_(vrt, vra) -#define vxor(vrt, vra, vrb) vxor_(vrt, vra, vrb) -#define vand(vrt, vra, vrb) vand_(vrt, vra, vrb) -#define vsro(vrt, vra, vrb) vsro_(vrt, vra, vrb) -#define vsl(vrt, vra, vrb) vsl_(vrt, vra, vrb) -#define vsldoi(vt, va, vb, sh) vsldoi_(vt, va, vb, sh) -#define vsr(vrt, vra, vrb) vsr_(vrt, vra, vrb) -#define vaddcuw(vrt, vra, vrb) vaddcuw_(vrt, vra, vrb) -#define vadduwm(vrt, vra, vrb) vadduwm_(vrt, vra, vrb) -#define vsububm(vrt, vra, vrb) vsububm_(vrt, vra, vrb) -#define vsubuwm(vrt, vra, vrb) vsubuwm_(vrt, vra, vrb) -#define vsrw(vrt, vra, vrb) vsrw_(vrt, vra, vrb) -#define vcipher(vt, va, vb) vcipher_(vt, va, vb) -#define vcipherlast(vt, va, vb) vcipherlast_(vt, va, vb) -#define vncipher(vt, va, vb) vncipher_(vt, va, vb) -#define vncipherlast(vt, va, vb) vncipherlast_(vt, va, vb) -#define vperm(vt, va, vb, vc) vperm_(vt, va, vb, vc) -#define vpmsumd(vt, va, vb) vpmsumd_(vt, va, vb) -#define xxpermdi(vt, va, vb, d) xxpermdi_(vt, va, vb, d) - -#define lxvw4x_(xt, ra, rb) "\tlxvw4x\t" #xt "," #ra "," #rb "\n" -#define stxvw4x_(xt, ra, rb) "\tstxvw4x\t" #xt "," #ra "," #rb "\n" - -#define label(foo) #foo "%=:\n" -#define bdnz_(foo) "\tbdnz\t" #foo "%=\n" -#define bdz_(foo) "\tbdz\t" #foo "%=\n" -#define beq_(foo) "\tbeq\t" #foo "%=\n" - -#define li_(rx, value) "\tli\t" #rx "," #value "\n" -#define addi_(rx, ra, imm) "\taddi\t" #rx "," #ra "," #imm "\n" -#define cmpldi_(rx, imm) "\tcmpldi\t" #rx "," #imm "\n" -#define mtctr_(rx) "\tmtctr\t" #rx "\n" -#define vspltb_(vrt, vrb, uim) "\tvspltb\t" #vrt "," #vrb "," #uim "\n" -#define vspltw_(vrt, vrb, uim) "\tvspltw\t" #vrt "," #vrb "," #uim "\n" -#define vspltisb_(vrt, imm) "\tvspltisb\t" #vrt "," #imm "\n" -#define vspltisw_(vrt, imm) "\tvspltisw\t" #vrt "," #imm "\n" -#define vrlw_(vrt, vra, vrb) "\tvrlw\t" #vrt "," #vra "," #vrb "\n" -#define vsbox_(vrt, vra) "\tvsbox\t" #vrt "," #vra "\n" -#define vxor_(vrt, vra, vrb) "\tvxor\t" #vrt "," #vra "," #vrb "\n" -#define vand_(vrt, vra, vrb) "\tvand\t" #vrt "," #vra "," #vrb "\n" -#define vsro_(vrt, vra, vrb) "\tvsro\t" #vrt "," #vra "," #vrb "\n" -#define vsl_(vrt, vra, vrb) "\tvsl\t" #vrt "," #vra "," #vrb "\n" -#define vsldoi_(vt, va, vb, sh) "\tvsldoi\t" #vt "," #va "," #vb "," #sh "\n" -#define vsr_(vrt, vra, vrb) "\tvsr\t" #vrt "," #vra "," #vrb "\n" -#define vaddcuw_(vrt, vra, vrb) "\tvaddcuw\t" #vrt "," #vra "," #vrb "\n" -#define vadduwm_(vrt, vra, vrb) "\tvadduwm\t" #vrt "," #vra "," #vrb "\n" -#define vsububm_(vrt, vra, vrb) "\tvsububm\t" #vrt "," #vra "," #vrb "\n" -#define vsubuwm_(vrt, vra, vrb) "\tvsubuwm\t" #vrt "," #vra "," #vrb "\n" -#define vsrw_(vrt, vra, vrb) "\tvsrw\t" #vrt "," #vra "," #vrb "\n" -#define vcipher_(vt, va, vb) "\tvcipher\t" #vt "," #va "," #vb "\n" -#define vcipherlast_(vt, va, vb) "\tvcipherlast\t" #vt "," #va "," #vb "\n" -#define vncipher_(vt, va, vb) "\tvncipher\t" #vt "," #va "," #vb "\n" -#define vncipherlast_(vt, va, vb) "\tvncipherlast\t" #vt "," #va "," #vb "\n" -#define vperm_(vt, va, vb, vc) "\tvperm\t" #vt "," #va "," #vb "," #vc "\n" -#define vpmsumd_(vt, va, vb) "\tvpmsumd\t" #vt "," #va "," #vb "\n" -#define xxpermdi_(vt, va, vb, d) "\txxpermdi\t" #vt "," #va "," #vb "," #d "\n" - -#endif - -/* ==================================================================== */ -/* - * Special "activate intrinsics" code, needed for some compiler versions. - * This is defined at the end of this file, so that it won't impact any - * of the inline functions defined previously; and it is controlled by - * a specific macro defined in the caller code. - * - * Calling code conventions: - * - * - Caller must define BR_ENABLE_INTRINSICS before including "inner.h". - * - Functions that use intrinsics must be enclosed in an "enabled" - * region (between BR_TARGETS_X86_UP and BR_TARGETS_X86_DOWN). - * - Functions that use intrinsics must be tagged with the appropriate - * BR_TARGET(). - */ - -#if BR_ENABLE_INTRINSICS && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005) - -/* - * x86 intrinsics (both 32-bit and 64-bit). - */ -#if BR_i386 || BR_amd64 - -/* - * On GCC before version 5.0, we need to use the pragma to enable the - * target options globally, because the 'target' function attribute - * appears to be unreliable. Before 4.6 we must also avoid the - * push_options / pop_options mechanism, because it tends to trigger - * some internal compiler errors. - */ -#if BR_GCC && !BR_GCC_5_0 -#if BR_GCC_4_6 -#define BR_TARGETS_X86_UP \ - _Pragma("GCC push_options") \ - _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")") -#define BR_TARGETS_X86_DOWN \ - _Pragma("GCC pop_options") -#else -#define BR_TARGETS_X86_UP \ - _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")") -#endif -#define BR_TARGETS_X86_DOWN -#pragma GCC diagnostic ignored "-Wpsabi" -#endif - -#if BR_CLANG && !BR_CLANG_3_8 -#undef __SSE2__ -#undef __SSE3__ -#undef __SSSE3__ -#undef __SSE4_1__ -#undef __AES__ -#undef __PCLMUL__ -#undef __RDRND__ -#define __SSE2__ 1 -#define __SSE3__ 1 -#define __SSSE3__ 1 -#define __SSE4_1__ 1 -#define __AES__ 1 -#define __PCLMUL__ 1 -#define __RDRND__ 1 -#endif - -#ifndef BR_TARGETS_X86_UP -#define BR_TARGETS_X86_UP -#endif -#ifndef BR_TARGETS_X86_DOWN -#define BR_TARGETS_X86_DOWN -#endif - -#if BR_GCC || BR_CLANG -BR_TARGETS_X86_UP -#include -#include -#define br_bswap32 __builtin_bswap32 -BR_TARGETS_X86_DOWN -#endif - -#if BR_MSC -#include -#include -#include -#define br_bswap32 _byteswap_ulong -#endif - -static inline int -br_cpuid(uint32_t mask_eax, uint32_t mask_ebx, - uint32_t mask_ecx, uint32_t mask_edx) -{ -#if BR_GCC || BR_CLANG - unsigned eax, ebx, ecx, edx; - - if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { - if ((eax & mask_eax) == mask_eax - && (ebx & mask_ebx) == mask_ebx - && (ecx & mask_ecx) == mask_ecx - && (edx & mask_edx) == mask_edx) - { - return 1; - } - } -#elif BR_MSC - int info[4]; - - __cpuid(info, 1); - if (((uint32_t)info[0] & mask_eax) == mask_eax - && ((uint32_t)info[1] & mask_ebx) == mask_ebx - && ((uint32_t)info[2] & mask_ecx) == mask_ecx - && ((uint32_t)info[3] & mask_edx) == mask_edx) - { - return 1; - } -#endif - return 0; -} - -#endif - -#endif - -/* ==================================================================== */ - -#endif diff --git a/src/tls/bearssl/md5.c b/src/tls/bearssl/md5.c deleted file mode 100644 index c6dff1940..000000000 --- a/src/tls/bearssl/md5.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) -#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C)) -#define H(B, C, D) ((B) ^ (C) ^ (D)) -#define I(B, C, D) ((C) ^ ((B) | ~(D))) - -#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - -/* see inner.h */ -const uint32_t br_md5_IV[4] = { - 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 -}; - -static const uint32_t K[64] = { - 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, - 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, - 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, - 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, - - 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, - 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, - 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, - 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, - - 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, - 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, - 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, - 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, - - 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, - 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, - 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, - 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 -}; - -static const unsigned char MP[48] = { - 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, - 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, - 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 -}; - -/* see inner.h */ -void -br_md5_round(const unsigned char *buf, uint32_t *val) -{ - uint32_t m[16]; - uint32_t a, b, c, d; - int i; - - a = val[0]; - b = val[1]; - c = val[2]; - d = val[3]; - /* obsolete - for (i = 0; i < 16; i ++) { - m[i] = br_dec32le(buf + (i << 2)); - } - */ - br_range_dec32le(m, 16, buf); - - for (i = 0; i < 16; i += 4) { - a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7); - d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12); - c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17); - b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22); - } - for (i = 16; i < 32; i += 4) { - a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5); - d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9); - c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14); - b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20); - } - for (i = 32; i < 48; i += 4) { - a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4); - d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11); - c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16); - b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23); - } - for (i = 48; i < 64; i += 4) { - a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6); - d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10); - c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15); - b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21); - } - - val[0] += a; - val[1] += b; - val[2] += c; - val[3] += d; -} - -/* see bearssl.h */ -void -br_md5_init(br_md5_context *cc) -{ - cc->vtable = &br_md5_vtable; - memcpy(cc->val, br_md5_IV, sizeof cc->val); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_md5_update(br_md5_context *cc, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)cc->count & 63; - while (len > 0) { - size_t clen; - - clen = 64 - ptr; - if (clen > len) { - clen = len; - } - memcpy(cc->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - cc->count += (uint64_t)clen; - if (ptr == 64) { - br_md5_round(cc->buf, cc->val); - ptr = 0; - } - } -} - -/* see bearssl.h */ -void -br_md5_out(const br_md5_context *cc, void *dst) -{ - unsigned char buf[64]; - uint32_t val[4]; - size_t ptr; - - ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); - buf[ptr ++] = 0x80; - if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); - br_md5_round(buf, val); - memset(buf, 0, 56); - } else { - memset(buf + ptr, 0, 56 - ptr); - } - br_enc64le(buf + 56, cc->count << 3); - br_md5_round(buf, val); - br_range_enc32le(dst, val, 4); -} - -/* see bearssl.h */ -uint64_t -br_md5_state(const br_md5_context *cc, void *dst) -{ - br_range_enc32le(dst, cc->val, 4); - return cc->count; -} - -/* see bearssl.h */ -void -br_md5_set_state(br_md5_context *cc, const void *stb, uint64_t count) -{ - br_range_dec32le(cc->val, 4, stb); - cc->count = count; -} - -/* see bearssl.h */ -const br_hash_class br_md5_vtable = { - sizeof(br_md5_context), - BR_HASHDESC_ID(br_md5_ID) - | BR_HASHDESC_OUT(16) - | BR_HASHDESC_STATE(16) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING, - (void (*)(const br_hash_class **))&br_md5_init, - (void (*)(const br_hash_class **, const void *, size_t))&br_md5_update, - (void (*)(const br_hash_class *const *, void *))&br_md5_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_md5_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_md5_set_state -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/md5sha1.c b/src/tls/bearssl/md5sha1.c deleted file mode 100644 index 1357f9084..000000000 --- a/src/tls/bearssl/md5sha1.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl.h */ -void -br_md5sha1_init(br_md5sha1_context *cc) -{ - cc->vtable = &br_md5sha1_vtable; - memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5); - memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)cc->count & 63; - while (len > 0) { - size_t clen; - - clen = 64 - ptr; - if (clen > len) { - clen = len; - } - memcpy(cc->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - cc->count += (uint64_t)clen; - if (ptr == 64) { - br_md5_round(cc->buf, cc->val_md5); - br_sha1_round(cc->buf, cc->val_sha1); - ptr = 0; - } - } -} - -/* see bearssl.h */ -void -br_md5sha1_out(const br_md5sha1_context *cc, void *dst) -{ - unsigned char buf[64]; - uint32_t val_md5[4]; - uint32_t val_sha1[5]; - size_t ptr; - unsigned char *out; - uint64_t count; - - count = cc->count; - ptr = (size_t)count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val_md5, cc->val_md5, sizeof val_md5); - memcpy(val_sha1, cc->val_sha1, sizeof val_sha1); - buf[ptr ++] = 0x80; - if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); - br_md5_round(buf, val_md5); - br_sha1_round(buf, val_sha1); - memset(buf, 0, 56); - } else { - memset(buf + ptr, 0, 56 - ptr); - } - count <<= 3; - br_enc64le(buf + 56, count); - br_md5_round(buf, val_md5); - br_enc64be(buf + 56, count); - br_sha1_round(buf, val_sha1); - out = dst; - br_range_enc32le(out, val_md5, 4); - br_range_enc32be(out + 16, val_sha1, 5); -} - -/* see bearssl.h */ -uint64_t -br_md5sha1_state(const br_md5sha1_context *cc, void *dst) -{ - unsigned char *out; - - out = dst; - br_range_enc32le(out, cc->val_md5, 4); - br_range_enc32be(out + 16, cc->val_sha1, 5); - return cc->count; -} - -/* see bearssl.h */ -void -br_md5sha1_set_state(br_md5sha1_context *cc, const void *stb, uint64_t count) -{ - const unsigned char *buf; - - buf = stb; - br_range_dec32le(cc->val_md5, 4, buf); - br_range_dec32be(cc->val_sha1, 5, buf + 16); - cc->count = count; -} - -/* see bearssl.h */ -const br_hash_class br_md5sha1_vtable = { - sizeof(br_md5sha1_context), - BR_HASHDESC_ID(br_md5sha1_ID) - | BR_HASHDESC_OUT(36) - | BR_HASHDESC_STATE(36) - | BR_HASHDESC_LBLEN(6), - (void (*)(const br_hash_class **))&br_md5sha1_init, - (void (*)(const br_hash_class **, const void *, size_t)) - &br_md5sha1_update, - (void (*)(const br_hash_class *const *, void *)) - &br_md5sha1_out, - (uint64_t (*)(const br_hash_class *const *, void *)) - &br_md5sha1_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_md5sha1_set_state -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/mgf1.c b/src/tls/bearssl/mgf1.c deleted file mode 100644 index 409306ed1..000000000 --- a/src/tls/bearssl/mgf1.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_mgf1_xor(void *data, size_t len, - const br_hash_class *dig, const void *seed, size_t seed_len) -{ - unsigned char *buf; - size_t u, hlen; - uint32_t c; - - buf = data; - hlen = br_digest_size(dig); - for (u = 0, c = 0; u < len; u += hlen, c ++) { - br_hash_compat_context hc; - unsigned char tmp[64]; - size_t v; - - hc.vtable = dig; - dig->init(&hc.vtable); - dig->update(&hc.vtable, seed, seed_len); - br_enc32be(tmp, c); - dig->update(&hc.vtable, tmp, 4); - dig->out(&hc.vtable, tmp); - for (v = 0; v < hlen; v ++) { - if ((u + v) >= len) { - break; - } - buf[u + v] ^= tmp[v]; - } - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/multihash.c b/src/tls/bearssl/multihash.c deleted file mode 100644 index 4a2805922..000000000 --- a/src/tls/bearssl/multihash.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * An aggregate context that is large enough for all supported hash - * functions. - */ -typedef union { - const br_hash_class *vtable; - br_md5_context md5; - br_sha1_context sha1; - br_sha224_context sha224; - br_sha256_context sha256; - br_sha384_context sha384; - br_sha512_context sha512; -} gen_hash_context; - -/* - * Get the offset to the state for a specific hash function within the - * context structure. This shall be called only for the supported hash - * functions, - */ -static size_t -get_state_offset(int id) -{ - if (id >= 5) { - /* - * SHA-384 has id 5, and SHA-512 has id 6. Both use - * eight 64-bit words for their state. - */ - return offsetof(br_multihash_context, val_64) - + ((size_t)(id - 5) * (8 * sizeof(uint64_t))); - } else { - /* - * MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and - * SHA-256 has id 4. They use 32-bit words for their - * states (4 words for MD5, 5 for SHA-1, 8 for SHA-224 - * and 8 for SHA-256). - */ - unsigned x; - - x = id - 1; - x = ((x + (x & (x >> 1))) << 2) + (x >> 1); - return offsetof(br_multihash_context, val_32) - + x * sizeof(uint32_t); - } -} - -/* see bearssl_hash.h */ -void -br_multihash_zero(br_multihash_context *ctx) -{ - /* - * This is not standard, but yields very short and efficient code, - * and it works "everywhere". - */ - memset(ctx, 0, sizeof *ctx); -} - -/* see bearssl_hash.h */ -void -br_multihash_init(br_multihash_context *ctx) -{ - int i; - - ctx->count = 0; - for (i = 1; i <= 6; i ++) { - const br_hash_class *hc; - - hc = ctx->impl[i - 1]; - if (hc != NULL) { - gen_hash_context g; - - hc->init(&g.vtable); - hc->state(&g.vtable, - (unsigned char *)ctx + get_state_offset(i)); - } - } -} - -/* see bearssl_hash.h */ -void -br_multihash_update(br_multihash_context *ctx, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)ctx->count & 127; - while (len > 0) { - size_t clen; - - clen = 128 - ptr; - if (clen > len) { - clen = len; - } - memcpy(ctx->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - ctx->count += (uint64_t)clen; - if (ptr == 128) { - int i; - - for (i = 1; i <= 6; i ++) { - const br_hash_class *hc; - - hc = ctx->impl[i - 1]; - if (hc != NULL) { - gen_hash_context g; - unsigned char *state; - - state = (unsigned char *)ctx - + get_state_offset(i); - hc->set_state(&g.vtable, - state, ctx->count - 128); - hc->update(&g.vtable, ctx->buf, 128); - hc->state(&g.vtable, state); - } - } - ptr = 0; - } - } -} - -/* see bearssl_hash.h */ -size_t -br_multihash_out(const br_multihash_context *ctx, int id, void *dst) -{ - const br_hash_class *hc; - gen_hash_context g; - const unsigned char *state; - - hc = ctx->impl[id - 1]; - if (hc == NULL) { - return 0; - } - state = (const unsigned char *)ctx + get_state_offset(id); - hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127); - hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127); - hc->out(&g.vtable, dst); - return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/pemdec.c b/src/tls/bearssl/pemdec.c deleted file mode 100644 index 0ec43aa74..000000000 --- a/src/tls/bearssl/pemdec.c +++ /dev/null @@ -1,531 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_pem_decoder_init_main(void *t0ctx); - -void br_pem_decoder_run(void *t0ctx); - - - -#include "inner.h" - -#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu))) - -/* see bearssl_pem.h */ -void -br_pem_decoder_init(br_pem_decoder_context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - ctx->cpu.dp = &ctx->dp_stack[0]; - ctx->cpu.rp = &ctx->rp_stack[0]; - br_pem_decoder_init_main(&ctx->cpu); - br_pem_decoder_run(&ctx->cpu); -} - -/* see bearssl_pem.h */ -size_t -br_pem_decoder_push(br_pem_decoder_context *ctx, - const void *data, size_t len) -{ - if (ctx->event) { - return 0; - } - ctx->hbuf = data; - ctx->hlen = len; - br_pem_decoder_run(&ctx->cpu); - return len - ctx->hlen; -} - -/* see bearssl_pem.h */ -int -br_pem_decoder_event(br_pem_decoder_context *ctx) -{ - int event; - - event = ctx->event; - ctx->event = 0; - return event; -} - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, - 0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00 -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, - 0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05, - 0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01, - 0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27, - 0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00, - 0x01, 0x01, 0x7F, 0x03, 0x00, 0x25, 0x01, 0x00, 0x18, 0x0D, 0x06, 0x03, - 0x13, 0x04, 0x3C, 0x01, 0x7F, 0x18, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00, - 0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x23, 0x01, - 0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x18, 0x0D, 0x06, 0x09, 0x13, 0x01, - 0x00, 0x23, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x18, 0x0D, 0x06, - 0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01, - 0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C, - 0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31, - 0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, - 0x02, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, - 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, - 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, - 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, - 0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E, - 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00, - 0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03, - 0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, - 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, - 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, - 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05, - 0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01, - 0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x02, - 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02, - 0x00, 0x01, 0x10, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1C, 0x02, - 0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x24, 0x06, - 0x02, 0x04, 0x7B, 0x04, 0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04, - 0x20, 0x01, 0x7F, 0x00, 0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05, - 0x13, 0x20, 0x01, 0x00, 0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00, - 0x00, 0x1E, 0x04, 0x5E, 0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x22, 0x01, - 0x80, 0x7F, 0x2B, 0x14, 0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00, - 0x2C, 0x14, 0x31, 0x05, 0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14, - 0x01, 0x80, 0x61, 0x0E, 0x1B, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03, - 0x01, 0x20, 0x08, 0x00, 0x01, 0x14, 0x03, 0x00, 0x1B, 0x18, 0x05, 0x05, - 0x20, 0x2E, 0x01, 0x00, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06, - 0x20, 0x02, 0x00, 0x1B, 0x08, 0x00, 0x14, 0x01, 0x0D, 0x0D, 0x06, 0x03, - 0x13, 0x04, 0x03, 0x2A, 0x18, 0x1A, 0x1E, 0x1B, 0x1F, 0x1B, 0x04, 0x59, - 0x00, 0x19, 0x14, 0x1D, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00, - 0x21, 0x1A, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04, - 0x78, 0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C, - 0x06, 0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13, - 0x02, 0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1F, 0x14, 0x22, 0x07, 0x17, - 0x01, 0x2D, 0x0C, 0x06, 0x08, 0x22, 0x07, 0x1E, 0x01, 0x00, 0x1B, 0x1A, - 0x00, 0x04, 0x69, 0x22, 0x1A, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1B, - 0x01, 0x20, 0x0B, 0x10, 0x00 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 15, - 19, - 24, - 29, - 67, - 149, - 384, - 396, - 431, - 450, - 460, - 479, - 523, - 534, - 539, - 549, - 574, - 601 -}; - -#define T0_INTERPRETED 29 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_pem_decoder_init_main, 38) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_pem_decoder_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 8: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 9: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 10: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 11: { - /* <= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a <= b)); - - } - break; - case 12: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 13: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 14: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 15: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 16: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 17: { - /* co */ - T0_CO(); - } - break; - case 18: { - /* data-get8 */ - - size_t addr = T0_POP(); - T0_PUSH(t0_datablock[addr]); - - } - break; - case 19: { - /* drop */ - (void)T0_POP(); - } - break; - case 20: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 21: { - /* flush-buf */ - - if (CTX->ptr > 0) { - if (CTX->dest) { - CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr); - } - CTX->ptr = 0; - } - - } - break; - case 22: { - /* from-base64 */ - - uint32_t c = T0_POP(); - uint32_t p, q, r, z; - p = c - 0x41; - q = c - 0x61; - r = c - 0x30; - - z = ((p + 2) & -LT(p, 26)) - | ((q + 28) & -LT(q, 26)) - | ((r + 54) & -LT(r, 10)) - | (64 & -EQ(c, 0x2B)) - | (65 & -EQ(c, 0x2F)) - | EQ(c, 0x3D); - T0_PUSHi((int32_t)z - 2); - - } - break; - case 23: { - /* get8 */ - - size_t addr = T0_POP(); - T0_PUSH(*((unsigned char *)CTX + addr)); - - } - break; - case 24: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 25: { - /* read8-native */ - - if (CTX->hlen > 0) { - T0_PUSH(*CTX->hbuf ++); - CTX->hlen --; - } else { - T0_PUSHi(-1); - } - - } - break; - case 26: { - /* set8 */ - - size_t addr = T0_POP(); - unsigned x = T0_POP(); - *((unsigned char *)CTX + addr) = x; - - } - break; - case 27: { - /* swap */ - T0_SWAP(); - } - break; - case 28: { - /* write8 */ - - unsigned char x = (unsigned char)T0_POP(); - CTX->buf[CTX->ptr ++] = x; - if (CTX->ptr == sizeof CTX->buf) { - if (CTX->dest) { - CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf); - } - CTX->ptr = 0; - } - - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/pemenc.c b/src/tls/bearssl/pemenc.c deleted file mode 100644 index 81c32d067..000000000 --- a/src/tls/bearssl/pemenc.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Get the appropriate Base64 character for a numeric value in the - * 0..63 range. This is constant-time. - */ -static char -b64char(uint32_t x) -{ - /* - * Values 0 to 25 map to 0x41..0x5A ('A' to 'Z') - * Values 26 to 51 map to 0x61..0x7A ('a' to 'z') - * Values 52 to 61 map to 0x30..0x39 ('0' to '9') - * Value 62 maps to 0x2B ('+') - * Value 63 maps to 0x2F ('/') - */ - uint32_t a, b, c; - - a = x - 26; - b = x - 52; - c = x - 62; - - /* - * Looking at bits 8..15 of values a, b and c: - * - * x a b c - * --------------------- - * 0..25 FF FF FF - * 26..51 00 FF FF - * 52..61 00 00 FF - * 62..63 00 00 00 - */ - return (char)(((x + 0x41) & ((a & b & c) >> 8)) - | ((x + (0x61 - 26)) & ((~a & b & c) >> 8)) - | ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8)) - | ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8))); -} - -/* see bearssl_pem.h */ -size_t -br_pem_encode(void *dest, const void *data, size_t len, - const char *banner, unsigned flags) -{ - size_t dlen, banner_len, lines; - char *d; - unsigned char *buf; - size_t u; - int off, lim; - - banner_len = strlen(banner); - /* FIXME: try to avoid divisions here, as they may pull - an extra libc function. */ - if ((flags & BR_PEM_LINE64) != 0) { - lines = (len + 47) / 48; - } else { - lines = (len + 56) / 57; - } - dlen = (banner_len << 1) + 30 + (((len + 2) / 3) << 2) - + lines + 2; - if ((flags & BR_PEM_CRLF) != 0) { - dlen += lines + 2; - } - - if (dest == NULL) { - return dlen; - } - - d = dest; - - /* - * We always move the source data to the end of output buffer; - * the encoding process never "catches up" except at the very - * end. This also handles all conditions of partial or total - * overlap. - */ - buf = (unsigned char *)d + dlen - len; - memmove(buf, data, len); - - memcpy(d, "-----BEGIN ", 11); - d += 11; - memcpy(d, banner, banner_len); - d += banner_len; - memcpy(d, "-----", 5); - d += 5; - if ((flags & BR_PEM_CRLF) != 0) { - *d ++ = 0x0D; - } - *d ++ = 0x0A; - - off = 0; - lim = (flags & BR_PEM_LINE64) != 0 ? 16 : 19; - for (u = 0; (u + 2) < len; u += 3) { - uint32_t w; - - w = ((uint32_t)buf[u] << 16) - | ((uint32_t)buf[u + 1] << 8) - | (uint32_t)buf[u + 2]; - *d ++ = b64char(w >> 18); - *d ++ = b64char((w >> 12) & 0x3F); - *d ++ = b64char((w >> 6) & 0x3F); - *d ++ = b64char(w & 0x3F); - if (++ off == lim) { - off = 0; - if ((flags & BR_PEM_CRLF) != 0) { - *d ++ = 0x0D; - } - *d ++ = 0x0A; - } - } - if (u < len) { - uint32_t w; - - w = (uint32_t)buf[u] << 16; - if (u + 1 < len) { - w |= (uint32_t)buf[u + 1] << 8; - } - *d ++ = b64char(w >> 18); - *d ++ = b64char((w >> 12) & 0x3F); - if (u + 1 < len) { - *d ++ = b64char((w >> 6) & 0x3F); - } else { - *d ++ = 0x3D; - } - *d ++ = 0x3D; - off ++; - } - if (off != 0) { - if ((flags & BR_PEM_CRLF) != 0) { - *d ++ = 0x0D; - } - *d ++ = 0x0A; - } - - memcpy(d, "-----END ", 9); - d += 9; - memcpy(d, banner, banner_len); - d += banner_len; - memcpy(d, "-----", 5); - d += 5; - if ((flags & BR_PEM_CRLF) != 0) { - *d ++ = 0x0D; - } - *d ++ = 0x0A; - - /* Final zero, not counted in returned length. */ - *d ++ = 0x00; - - return dlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/poly1305_ctmul.c b/src/tls/bearssl/poly1305_ctmul.c deleted file mode 100644 index 1ebdf82b4..000000000 --- a/src/tls/bearssl/poly1305_ctmul.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Perform the inner processing of blocks for Poly1305. The accumulator - * and the r key are provided as arrays of 26-bit words (these words - * are allowed to have an extra bit, i.e. use 27 bits). - * - * On output, all accumulator words fit on 26 bits, except acc[1], which - * may be slightly larger (but by a very small amount only). - */ -static void -poly1305_inner(uint32_t *acc, const uint32_t *r, const void *data, size_t len) -{ - /* - * Implementation notes: we split the 130-bit values into five - * 26-bit words. This gives us some space for carries. - * - * This code is inspired from the public-domain code available - * on: - * https://github.com/floodyberry/poly1305-donna - * - * Since we compute modulo 2^130-5, the "upper words" become - * low words with a factor of 5; that is, x*2^130 = x*5 mod p. - */ - const unsigned char *buf; - uint32_t a0, a1, a2, a3, a4; - uint32_t r0, r1, r2, r3, r4; - uint32_t u1, u2, u3, u4; - - r0 = r[0]; - r1 = r[1]; - r2 = r[2]; - r3 = r[3]; - r4 = r[4]; - - u1 = r1 * 5; - u2 = r2 * 5; - u3 = r3 * 5; - u4 = r4 * 5; - - a0 = acc[0]; - a1 = acc[1]; - a2 = acc[2]; - a3 = acc[3]; - a4 = acc[4]; - - buf = data; - while (len > 0) { - uint64_t w0, w1, w2, w3, w4; - uint64_t c; - unsigned char tmp[16]; - - /* - * If there is a partial block, right-pad it with zeros. - */ - if (len < 16) { - memset(tmp, 0, sizeof tmp); - memcpy(tmp, buf, len); - buf = tmp; - len = 16; - } - - /* - * Decode next block and apply the "high bit"; that value - * is added to the accumulator. - */ - a0 += br_dec32le(buf) & 0x03FFFFFF; - a1 += (br_dec32le(buf + 3) >> 2) & 0x03FFFFFF; - a2 += (br_dec32le(buf + 6) >> 4) & 0x03FFFFFF; - a3 += (br_dec32le(buf + 9) >> 6) & 0x03FFFFFF; - a4 += (br_dec32le(buf + 12) >> 8) | 0x01000000; - - /* - * Compute multiplication. - */ -#define M(x, y) ((uint64_t)(x) * (uint64_t)(y)) - - w0 = M(a0, r0) + M(a1, u4) + M(a2, u3) + M(a3, u2) + M(a4, u1); - w1 = M(a0, r1) + M(a1, r0) + M(a2, u4) + M(a3, u3) + M(a4, u2); - w2 = M(a0, r2) + M(a1, r1) + M(a2, r0) + M(a3, u4) + M(a4, u3); - w3 = M(a0, r3) + M(a1, r2) + M(a2, r1) + M(a3, r0) + M(a4, u4); - w4 = M(a0, r4) + M(a1, r3) + M(a2, r2) + M(a3, r1) + M(a4, r0); - -#undef M - /* - * Perform some (partial) modular reduction. This step is - * enough to keep values in ranges such that there won't - * be carry overflows. Most of the reduction was done in - * the multiplication step (by using the 'u*' values, and - * using the fact that 2^130 = -5 mod p); here we perform - * some carry propagation. - */ - c = w0 >> 26; - a0 = (uint32_t)w0 & 0x3FFFFFF; - w1 += c; - c = w1 >> 26; - a1 = (uint32_t)w1 & 0x3FFFFFF; - w2 += c; - c = w2 >> 26; - a2 = (uint32_t)w2 & 0x3FFFFFF; - w3 += c; - c = w3 >> 26; - a3 = (uint32_t)w3 & 0x3FFFFFF; - w4 += c; - c = w4 >> 26; - a4 = (uint32_t)w4 & 0x3FFFFFF; - a0 += (uint32_t)c * 5; - a1 += a0 >> 26; - a0 &= 0x3FFFFFF; - - buf += 16; - len -= 16; - } - - acc[0] = a0; - acc[1] = a1; - acc[2] = a2; - acc[3] = a3; - acc[4] = a4; -} - -/* see bearssl_block.h */ -void -br_poly1305_ctmul_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt) -{ - unsigned char pkey[32], foot[16]; - uint32_t r[5], acc[5], cc, ctl, hi; - uint64_t w; - int i; - - /* - * Compute the MAC key. The 'r' value is the first 16 bytes of - * pkey[]. - */ - memset(pkey, 0, sizeof pkey); - ichacha(key, iv, 0, pkey, sizeof pkey); - - /* - * If encrypting, ChaCha20 must run first, followed by Poly1305. - * When decrypting, the operations are reversed. - */ - if (encrypt) { - ichacha(key, iv, 1, data, len); - } - - /* - * Run Poly1305. We must process the AAD, then ciphertext, then - * the footer (with the lengths). Note that the AAD and ciphertext - * are meant to be padded with zeros up to the next multiple of 16, - * and the length of the footer is 16 bytes as well. - */ - - /* - * Decode the 'r' value into 26-bit words, with the "clamping" - * operation applied. - */ - r[0] = br_dec32le(pkey) & 0x03FFFFFF; - r[1] = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03; - r[2] = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF; - r[3] = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF; - r[4] = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF; - - /* - * Accumulator is 0. - */ - memset(acc, 0, sizeof acc); - - /* - * Process the additional authenticated data, ciphertext, and - * footer in due order. - */ - br_enc64le(foot, (uint64_t)aad_len); - br_enc64le(foot + 8, (uint64_t)len); - poly1305_inner(acc, r, aad, aad_len); - poly1305_inner(acc, r, data, len); - poly1305_inner(acc, r, foot, sizeof foot); - - /* - * Finalise modular reduction. This is done with carry propagation - * and applying the '2^130 = -5 mod p' rule. Note that the output - * of poly1035_inner() is already mostly reduced, since only - * acc[1] may be (very slightly) above 2^26. A single loop back - * to acc[1] will be enough to make the value fit in 130 bits. - */ - cc = 0; - for (i = 1; i <= 6; i ++) { - int j; - - j = (i >= 5) ? i - 5 : i; - acc[j] += cc; - cc = acc[j] >> 26; - acc[j] &= 0x03FFFFFF; - } - - /* - * We may still have a value in the 2^130-5..2^130-1 range, in - * which case we must reduce it again. The code below selects, - * in constant-time, between 'acc' and 'acc-p', - */ - ctl = GT(acc[0], 0x03FFFFFA); - for (i = 1; i < 5; i ++) { - ctl &= EQ(acc[i], 0x03FFFFFF); - } - cc = 5; - for (i = 0; i < 5; i ++) { - uint32_t t; - - t = (acc[i] + cc); - cc = t >> 26; - t &= 0x03FFFFFF; - acc[i] = MUX(ctl, t, acc[i]); - } - - /* - * Convert back the accumulator to 32-bit words, and add the - * 's' value (second half of pkey[]). That addition is done - * modulo 2^128. - */ - w = (uint64_t)acc[0] + ((uint64_t)acc[1] << 26) + br_dec32le(pkey + 16); - br_enc32le((unsigned char *)tag, (uint32_t)w); - w = (w >> 32) + ((uint64_t)acc[2] << 20) + br_dec32le(pkey + 20); - br_enc32le((unsigned char *)tag + 4, (uint32_t)w); - w = (w >> 32) + ((uint64_t)acc[3] << 14) + br_dec32le(pkey + 24); - br_enc32le((unsigned char *)tag + 8, (uint32_t)w); - hi = (uint32_t)(w >> 32) + (acc[4] << 8) + br_dec32le(pkey + 28); - br_enc32le((unsigned char *)tag + 12, hi); - - /* - * If decrypting, then ChaCha20 runs _after_ Poly1305. - */ - if (!encrypt) { - ichacha(key, iv, 1, data, len); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/poly1305_ctmul32.c b/src/tls/bearssl/poly1305_ctmul32.c deleted file mode 100644 index 948dd9e81..000000000 --- a/src/tls/bearssl/poly1305_ctmul32.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Perform the inner processing of blocks for Poly1305. - */ -static void -poly1305_inner(uint32_t *a, const uint32_t *r, const void *data, size_t len) -{ - /* - * Implementation notes: we split the 130-bit values into ten - * 13-bit words. This gives us some space for carries and allows - * using only 32x32->32 multiplications, which are way faster than - * 32x32->64 multiplications on the ARM Cortex-M0/M0+, and also - * help in making constant-time code on the Cortex-M3. - * - * Since we compute modulo 2^130-5, the "upper words" become - * low words with a factor of 5; that is, x*2^130 = x*5 mod p. - * This has already been integrated in the r[] array, which - * is extended to the 0..18 range. - * - * In each loop iteration, a[] and r[] words are 13-bit each, - * except a[1] which may use 14 bits. - */ - const unsigned char *buf; - - buf = data; - while (len > 0) { - unsigned char tmp[16]; - uint32_t b[10]; - unsigned u, v; - uint32_t z, cc1, cc2; - - /* - * If there is a partial block, right-pad it with zeros. - */ - if (len < 16) { - memset(tmp, 0, sizeof tmp); - memcpy(tmp, buf, len); - buf = tmp; - len = 16; - } - - /* - * Decode next block and apply the "high bit"; that value - * is added to the accumulator. - */ - v = br_dec16le(buf); - a[0] += v & 0x01FFF; - v >>= 13; - v |= buf[2] << 3; - v |= buf[3] << 11; - a[1] += v & 0x01FFF; - v >>= 13; - v |= buf[4] << 6; - a[2] += v & 0x01FFF; - v >>= 13; - v |= buf[5] << 1; - v |= buf[6] << 9; - a[3] += v & 0x01FFF; - v >>= 13; - v |= buf[7] << 4; - v |= buf[8] << 12; - a[4] += v & 0x01FFF; - v >>= 13; - v |= buf[9] << 7; - a[5] += v & 0x01FFF; - v >>= 13; - v |= buf[10] << 2; - v |= buf[11] << 10; - a[6] += v & 0x01FFF; - v >>= 13; - v |= buf[12] << 5; - a[7] += v & 0x01FFF; - v = br_dec16le(buf + 13); - a[8] += v & 0x01FFF; - v >>= 13; - v |= buf[15] << 3; - a[9] += v | 0x00800; - - /* - * At that point, all a[] values fit on 14 bits, while - * all r[] values fit on 13 bits. Thus products fit on - * 27 bits, and we can accumulate up to 31 of them in - * a 32-bit word and still have some room for carries. - */ - - /* - * Now a[] contains words with values up to 14 bits each. - * We perform the multiplication with r[]. - * - * The extended words of r[] may be larger than 13 bits - * (they are 5 times a 13-bit word) so the full summation - * may yield values up to 46 times a 27-bit word, which - * does not fit on a 32-bit word. To avoid that issue, we - * must split the loop below in two, with a carry - * propagation operation in the middle. - */ - cc1 = 0; - for (u = 0; u < 10; u ++) { - uint32_t s; - - s = cc1 - + MUL15(a[0], r[u + 9 - 0]) - + MUL15(a[1], r[u + 9 - 1]) - + MUL15(a[2], r[u + 9 - 2]) - + MUL15(a[3], r[u + 9 - 3]) - + MUL15(a[4], r[u + 9 - 4]); - b[u] = s & 0x1FFF; - cc1 = s >> 13; - } - cc2 = 0; - for (u = 0; u < 10; u ++) { - uint32_t s; - - s = b[u] + cc2 - + MUL15(a[5], r[u + 9 - 5]) - + MUL15(a[6], r[u + 9 - 6]) - + MUL15(a[7], r[u + 9 - 7]) - + MUL15(a[8], r[u + 9 - 8]) - + MUL15(a[9], r[u + 9 - 9]); - b[u] = s & 0x1FFF; - cc2 = s >> 13; - } - memcpy(a, b, sizeof b); - - /* - * The two carries "loop back" with a factor of 5. We - * propagate them into a[0] and a[1]. - */ - z = cc1 + cc2; - z += (z << 2) + a[0]; - a[0] = z & 0x1FFF; - a[1] += z >> 13; - - buf += 16; - len -= 16; - } -} - -/* see bearssl_block.h */ -void -br_poly1305_ctmul32_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt) -{ - unsigned char pkey[32], foot[16]; - uint32_t z, r[19], acc[10], cc, ctl; - int i; - - /* - * Compute the MAC key. The 'r' value is the first 16 bytes of - * pkey[]. - */ - memset(pkey, 0, sizeof pkey); - ichacha(key, iv, 0, pkey, sizeof pkey); - - /* - * If encrypting, ChaCha20 must run first, followed by Poly1305. - * When decrypting, the operations are reversed. - */ - if (encrypt) { - ichacha(key, iv, 1, data, len); - } - - /* - * Run Poly1305. We must process the AAD, then ciphertext, then - * the footer (with the lengths). Note that the AAD and ciphertext - * are meant to be padded with zeros up to the next multiple of 16, - * and the length of the footer is 16 bytes as well. - */ - - /* - * Decode the 'r' value into 13-bit words, with the "clamping" - * operation applied. - */ - z = br_dec32le(pkey) & 0x03FFFFFF; - r[9] = z & 0x1FFF; - r[10] = z >> 13; - z = (br_dec32le(pkey + 3) >> 2) & 0x03FFFF03; - r[11] = z & 0x1FFF; - r[12] = z >> 13; - z = (br_dec32le(pkey + 6) >> 4) & 0x03FFC0FF; - r[13] = z & 0x1FFF; - r[14] = z >> 13; - z = (br_dec32le(pkey + 9) >> 6) & 0x03F03FFF; - r[15] = z & 0x1FFF; - r[16] = z >> 13; - z = (br_dec32le(pkey + 12) >> 8) & 0x000FFFFF; - r[17] = z & 0x1FFF; - r[18] = z >> 13; - - /* - * Extend r[] with the 5x factor pre-applied. - */ - for (i = 0; i < 9; i ++) { - r[i] = MUL15(5, r[i + 10]); - } - - /* - * Accumulator is 0. - */ - memset(acc, 0, sizeof acc); - - /* - * Process the additional authenticated data, ciphertext, and - * footer in due order. - */ - br_enc64le(foot, (uint64_t)aad_len); - br_enc64le(foot + 8, (uint64_t)len); - poly1305_inner(acc, r, aad, aad_len); - poly1305_inner(acc, r, data, len); - poly1305_inner(acc, r, foot, sizeof foot); - - /* - * Finalise modular reduction. This is done with carry propagation - * and applying the '2^130 = -5 mod p' rule. Note that the output - * of poly1035_inner() is already mostly reduced, since only - * acc[1] may be (very slightly) above 2^13. A single loop back - * to acc[1] will be enough to make the value fit in 130 bits. - */ - cc = 0; - for (i = 1; i < 10; i ++) { - z = acc[i] + cc; - acc[i] = z & 0x1FFF; - cc = z >> 13; - } - z = acc[0] + cc + (cc << 2); - acc[0] = z & 0x1FFF; - acc[1] += z >> 13; - - /* - * We may still have a value in the 2^130-5..2^130-1 range, in - * which case we must reduce it again. The code below selects, - * in constant-time, between 'acc' and 'acc-p', - */ - ctl = GT(acc[0], 0x1FFA); - for (i = 1; i < 10; i ++) { - ctl &= EQ(acc[i], 0x1FFF); - } - acc[0] = MUX(ctl, acc[0] - 0x1FFB, acc[0]); - for (i = 1; i < 10; i ++) { - acc[i] &= ~(-ctl); - } - - /* - * Convert back the accumulator to 32-bit words, and add the - * 's' value (second half of pkey[]). That addition is done - * modulo 2^128. - */ - z = acc[0] + (acc[1] << 13) + br_dec16le(pkey + 16); - br_enc16le((unsigned char *)tag, z & 0xFFFF); - z = (z >> 16) + (acc[2] << 10) + br_dec16le(pkey + 18); - br_enc16le((unsigned char *)tag + 2, z & 0xFFFF); - z = (z >> 16) + (acc[3] << 7) + br_dec16le(pkey + 20); - br_enc16le((unsigned char *)tag + 4, z & 0xFFFF); - z = (z >> 16) + (acc[4] << 4) + br_dec16le(pkey + 22); - br_enc16le((unsigned char *)tag + 6, z & 0xFFFF); - z = (z >> 16) + (acc[5] << 1) + (acc[6] << 14) + br_dec16le(pkey + 24); - br_enc16le((unsigned char *)tag + 8, z & 0xFFFF); - z = (z >> 16) + (acc[7] << 11) + br_dec16le(pkey + 26); - br_enc16le((unsigned char *)tag + 10, z & 0xFFFF); - z = (z >> 16) + (acc[8] << 8) + br_dec16le(pkey + 28); - br_enc16le((unsigned char *)tag + 12, z & 0xFFFF); - z = (z >> 16) + (acc[9] << 5) + br_dec16le(pkey + 30); - br_enc16le((unsigned char *)tag + 14, z & 0xFFFF); - - /* - * If decrypting, then ChaCha20 runs _after_ Poly1305. - */ - if (!encrypt) { - ichacha(key, iv, 1, data, len); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/poly1305_ctmulq.c b/src/tls/bearssl/poly1305_ctmulq.c deleted file mode 100644 index b4426e528..000000000 --- a/src/tls/bearssl/poly1305_ctmulq.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -#if BR_INT128 - -#define MUL128(hi, lo, x, y) do { \ - unsigned __int128 mul128tmp; \ - mul128tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \ - (hi) = (uint64_t)(mul128tmp >> 64); \ - (lo) = (uint64_t)mul128tmp; \ - } while (0) - -#elif BR_UMUL128 - -#include - -#define MUL128(hi, lo, x, y) do { \ - (lo) = _umul128((x), (y), &(hi)); \ - } while (0) - -#endif - -#define MASK42 ((uint64_t)0x000003FFFFFFFFFF) -#define MASK44 ((uint64_t)0x00000FFFFFFFFFFF) - -/* - * The "accumulator" word is nominally a 130-bit value. We split it into - * words of 44 bits, each held in a 64-bit variable. - * - * If the current accumulator is a = a0 + a1*W + a2*W^2 (where W = 2^44) - * and r = r0 + r1*W + r2*W^2, then: - * - * a*r = (a0*r0) - * + (a0*r1 + a1*r0) * W - * + (a0*r2 + a1*r1 + a2*r0) * W^2 - * + (a1*r2 + a2*r1) * W^3 - * + (a2*r2) * W^4 - * - * We want to reduce that value modulo p = 2^130-5, so W^3 = 20 mod p, - * and W^4 = 20*W mod p. Thus, if we define u1 = 20*r1 and u2 = 20*r2, - * then the equations above become: - * - * b0 = a0*r0 + a1*u2 + a2*u1 - * b1 = a0*r1 + a1*r0 + a2*u2 - * b2 = a0*r2 + a1*r1 + a2*r0 - * - * In order to make u1 fit in 44 bits, we can change these equations - * into: - * - * b0 = a0*r0 + a1*u2 + a2*t1 - * b1 = a0*r1 + a1*r0 + a2*t2 - * b2 = a0*r2 + a1*r1 + a2*r0 - * - * Where t1 is u1 truncated to 44 bits, and t2 is u2 added to the extra - * bits of u1. Note that since r is clamped down to a 124-bit value, the - * values u2 and t2 fit on 44 bits too. - * - * The bx values are larger than 44 bits, so we may split them into a - * lower half (cx, 44 bits) and an upper half (dx). The new values for - * the accumulator are then: - * - * e0 = c0 + 20*d2 - * e1 = c1 + d0 - * e2 = c2 + d1 - * - * The equations allow for some room, i.e. the ax values may be larger - * than 44 bits. Similarly, the ex values will usually be larger than - * the ax. Thus, some sort of carry propagation must be done regularly, - * though not necessarily at each iteration. In particular, we do not - * need to compute the additions (for the bx values) over 128-bit - * quantities; we can stick to 64-bit computations. - * - * - * Since the 128-bit result of a 64x64 multiplication is actually - * represented over two 64-bit registers, it is cheaper to arrange for - * any split that happens between the "high" and "low" halves to be on - * that 64-bit boundary. This is done by left shifting the rx, ux and tx - * by 20 bits (since they all fit on 44 bits each, this shift is - * always possible). - */ - -static void -poly1305_inner_big(uint64_t *acc, uint64_t *r, const void *data, size_t len) -{ - -#define MX(hi, lo, m0, m1, m2) do { \ - uint64_t mxhi, mxlo; \ - MUL128(mxhi, mxlo, a0, m0); \ - (hi) = mxhi; \ - (lo) = mxlo >> 20; \ - MUL128(mxhi, mxlo, a1, m1); \ - (hi) += mxhi; \ - (lo) += mxlo >> 20; \ - MUL128(mxhi, mxlo, a2, m2); \ - (hi) += mxhi; \ - (lo) += mxlo >> 20; \ - } while (0) - - const unsigned char *buf; - uint64_t a0, a1, a2; - uint64_t r0, r1, r2, t1, t2, u2; - - r0 = r[0]; - r1 = r[1]; - r2 = r[2]; - t1 = r[3]; - t2 = r[4]; - u2 = r[5]; - a0 = acc[0]; - a1 = acc[1]; - a2 = acc[2]; - buf = data; - - while (len > 0) { - uint64_t v0, v1, v2; - uint64_t c0, c1, c2, d0, d1, d2; - - v0 = br_dec64le(buf + 0); - v1 = br_dec64le(buf + 8); - v2 = v1 >> 24; - v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; - v0 &= MASK44; - a0 += v0; - a1 += v1; - a2 += v2 + ((uint64_t)1 << 40); - MX(d0, c0, r0, u2, t1); - MX(d1, c1, r1, r0, t2); - MX(d2, c2, r2, r1, r0); - a0 = c0 + 20 * d2; - a1 = c1 + d0; - a2 = c2 + d1; - - v0 = br_dec64le(buf + 16); - v1 = br_dec64le(buf + 24); - v2 = v1 >> 24; - v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; - v0 &= MASK44; - a0 += v0; - a1 += v1; - a2 += v2 + ((uint64_t)1 << 40); - MX(d0, c0, r0, u2, t1); - MX(d1, c1, r1, r0, t2); - MX(d2, c2, r2, r1, r0); - a0 = c0 + 20 * d2; - a1 = c1 + d0; - a2 = c2 + d1; - - v0 = br_dec64le(buf + 32); - v1 = br_dec64le(buf + 40); - v2 = v1 >> 24; - v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; - v0 &= MASK44; - a0 += v0; - a1 += v1; - a2 += v2 + ((uint64_t)1 << 40); - MX(d0, c0, r0, u2, t1); - MX(d1, c1, r1, r0, t2); - MX(d2, c2, r2, r1, r0); - a0 = c0 + 20 * d2; - a1 = c1 + d0; - a2 = c2 + d1; - - v0 = br_dec64le(buf + 48); - v1 = br_dec64le(buf + 56); - v2 = v1 >> 24; - v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; - v0 &= MASK44; - a0 += v0; - a1 += v1; - a2 += v2 + ((uint64_t)1 << 40); - MX(d0, c0, r0, u2, t1); - MX(d1, c1, r1, r0, t2); - MX(d2, c2, r2, r1, r0); - a0 = c0 + 20 * d2; - a1 = c1 + d0; - a2 = c2 + d1; - - a1 += a0 >> 44; - a0 &= MASK44; - a2 += a1 >> 44; - a1 &= MASK44; - a0 += 20 * (a2 >> 44); - a2 &= MASK44; - - buf += 64; - len -= 64; - } - acc[0] = a0; - acc[1] = a1; - acc[2] = a2; - -#undef MX -} - -static void -poly1305_inner_small(uint64_t *acc, uint64_t *r, const void *data, size_t len) -{ - const unsigned char *buf; - uint64_t a0, a1, a2; - uint64_t r0, r1, r2, t1, t2, u2; - - r0 = r[0]; - r1 = r[1]; - r2 = r[2]; - t1 = r[3]; - t2 = r[4]; - u2 = r[5]; - a0 = acc[0]; - a1 = acc[1]; - a2 = acc[2]; - buf = data; - - while (len > 0) { - uint64_t v0, v1, v2; - uint64_t c0, c1, c2, d0, d1, d2; - unsigned char tmp[16]; - - if (len < 16) { - memcpy(tmp, buf, len); - memset(tmp + len, 0, (sizeof tmp) - len); - buf = tmp; - len = 16; - } - v0 = br_dec64le(buf + 0); - v1 = br_dec64le(buf + 8); - - v2 = v1 >> 24; - v1 = ((v0 >> 44) | (v1 << 20)) & MASK44; - v0 &= MASK44; - - a0 += v0; - a1 += v1; - a2 += v2 + ((uint64_t)1 << 40); - -#define MX(hi, lo, m0, m1, m2) do { \ - uint64_t mxhi, mxlo; \ - MUL128(mxhi, mxlo, a0, m0); \ - (hi) = mxhi; \ - (lo) = mxlo >> 20; \ - MUL128(mxhi, mxlo, a1, m1); \ - (hi) += mxhi; \ - (lo) += mxlo >> 20; \ - MUL128(mxhi, mxlo, a2, m2); \ - (hi) += mxhi; \ - (lo) += mxlo >> 20; \ - } while (0) - - MX(d0, c0, r0, u2, t1); - MX(d1, c1, r1, r0, t2); - MX(d2, c2, r2, r1, r0); - -#undef MX - - a0 = c0 + 20 * d2; - a1 = c1 + d0; - a2 = c2 + d1; - - a1 += a0 >> 44; - a0 &= MASK44; - a2 += a1 >> 44; - a1 &= MASK44; - a0 += 20 * (a2 >> 44); - a2 &= MASK44; - - buf += 16; - len -= 16; - } - acc[0] = a0; - acc[1] = a1; - acc[2] = a2; -} - -static inline void -poly1305_inner(uint64_t *acc, uint64_t *r, const void *data, size_t len) -{ - if (len >= 64) { - size_t len2; - - len2 = len & ~(size_t)63; - poly1305_inner_big(acc, r, data, len2); - data = (const unsigned char *)data + len2; - len -= len2; - } - if (len > 0) { - poly1305_inner_small(acc, r, data, len); - } -} - -/* see bearssl_block.h */ -void -br_poly1305_ctmulq_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt) -{ - unsigned char pkey[32], foot[16]; - uint64_t r[6], acc[3], r0, r1; - uint32_t v0, v1, v2, v3, v4; - uint64_t w0, w1, w2, w3; - uint32_t ctl; - - /* - * Compute the MAC key. The 'r' value is the first 16 bytes of - * pkey[]. - */ - memset(pkey, 0, sizeof pkey); - ichacha(key, iv, 0, pkey, sizeof pkey); - - /* - * If encrypting, ChaCha20 must run first, followed by Poly1305. - * When decrypting, the operations are reversed. - */ - if (encrypt) { - ichacha(key, iv, 1, data, len); - } - - /* - * Run Poly1305. We must process the AAD, then ciphertext, then - * the footer (with the lengths). Note that the AAD and ciphertext - * are meant to be padded with zeros up to the next multiple of 16, - * and the length of the footer is 16 bytes as well. - */ - - /* - * Apply the "clamping" on r. - */ - pkey[ 3] &= 0x0F; - pkey[ 4] &= 0xFC; - pkey[ 7] &= 0x0F; - pkey[ 8] &= 0xFC; - pkey[11] &= 0x0F; - pkey[12] &= 0xFC; - pkey[15] &= 0x0F; - - /* - * Decode the 'r' value into 44-bit words, left-shifted by 20 bits. - * Also compute the u1 and u2 values. - */ - r0 = br_dec64le(pkey + 0); - r1 = br_dec64le(pkey + 8); - r[0] = r0 << 20; - r[1] = ((r0 >> 24) | (r1 << 40)) & ~(uint64_t)0xFFFFF; - r[2] = (r1 >> 4) & ~(uint64_t)0xFFFFF; - r1 = 20 * (r[1] >> 20); - r[3] = r1 << 20; - r[5] = 20 * r[2]; - r[4] = (r[5] + (r1 >> 24)) & ~(uint64_t)0xFFFFF; - - /* - * Accumulator is 0. - */ - acc[0] = 0; - acc[1] = 0; - acc[2] = 0; - - /* - * Process the additional authenticated data, ciphertext, and - * footer in due order. - */ - br_enc64le(foot, (uint64_t)aad_len); - br_enc64le(foot + 8, (uint64_t)len); - poly1305_inner(acc, r, aad, aad_len); - poly1305_inner(acc, r, data, len); - poly1305_inner_small(acc, r, foot, sizeof foot); - - /* - * Finalise modular reduction. At that point, the value consists - * in three 44-bit values (the lowest one might be slightly above - * 2^44). Two loops shall be sufficient. - */ - acc[1] += (acc[0] >> 44); - acc[0] &= MASK44; - acc[2] += (acc[1] >> 44); - acc[1] &= MASK44; - acc[0] += 5 * (acc[2] >> 42); - acc[2] &= MASK42; - acc[1] += (acc[0] >> 44); - acc[0] &= MASK44; - acc[2] += (acc[1] >> 44); - acc[1] &= MASK44; - acc[0] += 5 * (acc[2] >> 42); - acc[2] &= MASK42; - - /* - * The value may still fall in the 2^130-5..2^130-1 range, in - * which case we must reduce it again. The code below selects, - * in constant-time, between 'acc' and 'acc-p'. We encode the - * value over four 32-bit integers to finish the operation. - */ - v0 = (uint32_t)acc[0]; - v1 = (uint32_t)(acc[0] >> 32) | ((uint32_t)acc[1] << 12); - v2 = (uint32_t)(acc[1] >> 20) | ((uint32_t)acc[2] << 24); - v3 = (uint32_t)(acc[2] >> 8); - v4 = (uint32_t)(acc[2] >> 40); - - ctl = GT(v0, 0xFFFFFFFA); - ctl &= EQ(v1, 0xFFFFFFFF); - ctl &= EQ(v2, 0xFFFFFFFF); - ctl &= EQ(v3, 0xFFFFFFFF); - ctl &= EQ(v4, 0x00000003); - v0 = MUX(ctl, v0 + 5, v0); - v1 = MUX(ctl, 0, v1); - v2 = MUX(ctl, 0, v2); - v3 = MUX(ctl, 0, v3); - - /* - * Add the "s" value. This is done modulo 2^128. Don't forget - * carry propagation... - */ - w0 = (uint64_t)v0 + (uint64_t)br_dec32le(pkey + 16); - w1 = (uint64_t)v1 + (uint64_t)br_dec32le(pkey + 20) + (w0 >> 32); - w2 = (uint64_t)v2 + (uint64_t)br_dec32le(pkey + 24) + (w1 >> 32); - w3 = (uint64_t)v3 + (uint64_t)br_dec32le(pkey + 28) + (w2 >> 32); - v0 = (uint32_t)w0; - v1 = (uint32_t)w1; - v2 = (uint32_t)w2; - v3 = (uint32_t)w3; - - /* - * Encode the tag. - */ - br_enc32le((unsigned char *)tag + 0, v0); - br_enc32le((unsigned char *)tag + 4, v1); - br_enc32le((unsigned char *)tag + 8, v2); - br_enc32le((unsigned char *)tag + 12, v3); - - /* - * If decrypting, then ChaCha20 runs _after_ Poly1305. - */ - if (!encrypt) { - ichacha(key, iv, 1, data, len); - } -} - -/* see bearssl_block.h */ -br_poly1305_run -br_poly1305_ctmulq_get(void) -{ - return &br_poly1305_ctmulq_run; -} - -#else - -/* see bearssl_block.h */ -br_poly1305_run -br_poly1305_ctmulq_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/poly1305_i15.c b/src/tls/bearssl/poly1305_i15.c deleted file mode 100644 index 519ddc592..000000000 --- a/src/tls/bearssl/poly1305_i15.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * This is a "reference" implementation of Poly1305 that uses the - * generic "i15" code for big integers. It is slow, but it handles all - * big-integer operations with generic code, thereby avoiding most - * tricky situations with carry propagation and modular reduction. - */ - -/* - * Modulus: 2^130-5. - */ -static const uint16_t P1305[] = { - 0x008A, - 0x7FFB, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x03FF -}; - -/* - * -p mod 2^15. - */ -#define P0I 0x4CCD - -/* - * R^2 mod p, for conversion to Montgomery representation (R = 2^135, - * since we use 9 words of 15 bits each, and 15*9 = 135). - */ -static const uint16_t R2[] = { - 0x008A, - 0x6400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 -}; - -/* - * Perform the inner processing of blocks for Poly1305. The "r" array - * is in Montgomery representation, while the "a" array is not. - */ -static void -poly1305_inner(uint16_t *a, const uint16_t *r, const void *data, size_t len) -{ - const unsigned char *buf; - - buf = data; - while (len > 0) { - unsigned char tmp[16], rev[16]; - uint16_t b[10]; - uint32_t ctl; - int i; - - /* - * If there is a partial block, right-pad it with zeros. - */ - if (len < 16) { - memset(tmp, 0, sizeof tmp); - memcpy(tmp, buf, len); - buf = tmp; - len = 16; - } - - /* - * Decode next block and apply the "high bit". Since - * decoding is little-endian, we must byte-swap the buffer. - */ - for (i = 0; i < 16; i ++) { - rev[i] = buf[15 - i]; - } - br_i15_decode_mod(b, rev, sizeof rev, P1305); - b[9] |= 0x0100; - - /* - * Add the accumulator to the decoded block (modular - * addition). - */ - ctl = br_i15_add(b, a, 1); - ctl |= NOT(br_i15_sub(b, P1305, 0)); - br_i15_sub(b, P1305, ctl); - - /* - * Multiply by r, result is the new accumulator value. - */ - br_i15_montymul(a, b, r, P1305, P0I); - - buf += 16; - len -= 16; - } -} - -/* - * Byteswap a 16-byte value. - */ -static void -byteswap16(unsigned char *buf) -{ - int i; - - for (i = 0; i < 8; i ++) { - unsigned x; - - x = buf[i]; - buf[i] = buf[15 - i]; - buf[15 - i] = x; - } -} - -/* see bearssl_block.h */ -void -br_poly1305_i15_run(const void *key, const void *iv, - void *data, size_t len, const void *aad, size_t aad_len, - void *tag, br_chacha20_run ichacha, int encrypt) -{ - unsigned char pkey[32], foot[16]; - uint16_t t[10], r[10], acc[10]; - - /* - * Compute the MAC key. The 'r' value is the first 16 bytes of - * pkey[]. - */ - memset(pkey, 0, sizeof pkey); - ichacha(key, iv, 0, pkey, sizeof pkey); - - /* - * If encrypting, ChaCha20 must run first, followed by Poly1305. - * When decrypting, the operations are reversed. - */ - if (encrypt) { - ichacha(key, iv, 1, data, len); - } - - /* - * Run Poly1305. We must process the AAD, then ciphertext, then - * the footer (with the lengths). Note that the AAD and ciphertext - * are meant to be padded with zeros up to the next multiple of 16, - * and the length of the footer is 16 bytes as well. - */ - - /* - * Apply the "clamping" operation on the encoded 'r' value. - */ - pkey[ 3] &= 0x0F; - pkey[ 7] &= 0x0F; - pkey[11] &= 0x0F; - pkey[15] &= 0x0F; - pkey[ 4] &= 0xFC; - pkey[ 8] &= 0xFC; - pkey[12] &= 0xFC; - - /* - * Decode the clamped 'r' value. Decoding should use little-endian - * so we must byteswap the value first. - */ - byteswap16(pkey); - br_i15_decode_mod(t, pkey, 16, P1305); - - /* - * Convert 'r' to Montgomery representation. - */ - br_i15_montymul(r, t, R2, P1305, P0I); - - /* - * Accumulator is 0. - */ - br_i15_zero(acc, 0x8A); - - /* - * Process the additional authenticated data, ciphertext, and - * footer in due order. - */ - br_enc64le(foot, (uint64_t)aad_len); - br_enc64le(foot + 8, (uint64_t)len); - poly1305_inner(acc, r, aad, aad_len); - poly1305_inner(acc, r, data, len); - poly1305_inner(acc, r, foot, sizeof foot); - - /* - * Decode the value 's'. Again, a byteswap is needed. - */ - byteswap16(pkey + 16); - br_i15_decode_mod(t, pkey + 16, 16, P1305); - - /* - * Add the value 's' to the accumulator. That addition is done - * modulo 2^128, so we just ignore the carry. - */ - br_i15_add(acc, t, 1); - - /* - * Encode the result (128 low bits) to the tag. Encoding should - * be little-endian. - */ - br_i15_encode(tag, 16, acc); - byteswap16(tag); - - /* - * If decrypting, then ChaCha20 runs _after_ Poly1305. - */ - if (!encrypt) { - ichacha(key, iv, 1, data, len); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/prf.c b/src/tls/bearssl/prf.c deleted file mode 100644 index d690438a2..000000000 --- a/src/tls/bearssl/prf.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -void -br_tls_phash(void *dst, size_t len, - const br_hash_class *dig, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed) -{ - unsigned char *buf; - unsigned char tmp[64], a[64]; - br_hmac_key_context kc; - br_hmac_context hc; - size_t label_len, hlen, u; - - if (len == 0) { - return; - } - buf = dst; - for (label_len = 0; label[label_len]; label_len ++); - hlen = br_digest_size(dig); - br_hmac_key_init(&kc, dig, secret, secret_len); - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, label, label_len); - for (u = 0; u < seed_num; u ++) { - br_hmac_update(&hc, seed[u].data, seed[u].len); - } - br_hmac_out(&hc, a); - for (;;) { - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, a, hlen); - br_hmac_update(&hc, label, label_len); - for (u = 0; u < seed_num; u ++) { - br_hmac_update(&hc, seed[u].data, seed[u].len); - } - br_hmac_out(&hc, tmp); - for (u = 0; u < hlen && u < len; u ++) { - buf[u] ^= tmp[u]; - } - buf += u; - len -= u; - if (len == 0) { - return; - } - br_hmac_init(&hc, &kc, 0); - br_hmac_update(&hc, a, hlen); - br_hmac_out(&hc, a); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/prf_md5sha1.c b/src/tls/bearssl/prf_md5sha1.c deleted file mode 100644 index 602f71f4e..000000000 --- a/src/tls/bearssl/prf_md5sha1.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl.h */ -void -br_tls10_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed) -{ - const unsigned char *s1; - size_t slen; - - s1 = secret; - slen = (secret_len + 1) >> 1; - memset(dst, 0, len); - br_tls_phash(dst, len, &br_md5_vtable, - s1, slen, label, seed_num, seed); - br_tls_phash(dst, len, &br_sha1_vtable, - s1 + secret_len - slen, slen, label, seed_num, seed); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/prf_sha256.c b/src/tls/bearssl/prf_sha256.c deleted file mode 100644 index 3a1926ff4..000000000 --- a/src/tls/bearssl/prf_sha256.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl.h */ -void -br_tls12_sha256_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed) -{ - memset(dst, 0, len); - br_tls_phash(dst, len, &br_sha256_vtable, - secret, secret_len, label, seed_num, seed); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/prf_sha384.c b/src/tls/bearssl/prf_sha384.c deleted file mode 100644 index 9bbf27b3b..000000000 --- a/src/tls/bearssl/prf_sha384.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl.h */ -void -br_tls12_sha384_prf(void *dst, size_t len, - const void *secret, size_t secret_len, const char *label, - size_t seed_num, const br_tls_prf_seed_chunk *seed) -{ - memset(dst, 0, len); - br_tls_phash(dst, len, &br_sha384_vtable, - secret, secret_len, label, seed_num, seed); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_keygen.c b/src/tls/bearssl/rsa_default_keygen.c deleted file mode 100644 index 701cf48c2..000000000 --- a/src/tls/bearssl/rsa_default_keygen.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_keygen -br_rsa_keygen_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_keygen; -#elif BR_LOMUL - return &br_rsa_i15_keygen; -#else - return &br_rsa_i31_keygen; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_modulus.c b/src/tls/bearssl/rsa_default_modulus.c deleted file mode 100644 index 5f0ad407d..000000000 --- a/src/tls/bearssl/rsa_default_modulus.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_compute_modulus -br_rsa_compute_modulus_get_default(void) -{ -#if BR_LOMUL - return &br_rsa_i15_compute_modulus; -#else - return &br_rsa_i31_compute_modulus; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_oaep_decrypt.c b/src/tls/bearssl/rsa_default_oaep_decrypt.c deleted file mode 100644 index 5de28e898..000000000 --- a/src/tls/bearssl/rsa_default_oaep_decrypt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_oaep_decrypt -br_rsa_oaep_decrypt_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_oaep_decrypt; -#elif BR_LOMUL - return &br_rsa_i15_oaep_decrypt; -#else - return &br_rsa_i31_oaep_decrypt; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_oaep_encrypt.c b/src/tls/bearssl/rsa_default_oaep_encrypt.c deleted file mode 100644 index 7dd768557..000000000 --- a/src/tls/bearssl/rsa_default_oaep_encrypt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_oaep_encrypt -br_rsa_oaep_encrypt_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_oaep_encrypt; -#elif BR_LOMUL - return &br_rsa_i15_oaep_encrypt; -#else - return &br_rsa_i31_oaep_encrypt; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_pkcs1_sign.c b/src/tls/bearssl/rsa_default_pkcs1_sign.c deleted file mode 100644 index bcdfae3c1..000000000 --- a/src/tls/bearssl/rsa_default_pkcs1_sign.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_sign -br_rsa_pkcs1_sign_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_pkcs1_sign; -#elif BR_LOMUL - return &br_rsa_i15_pkcs1_sign; -#else - return &br_rsa_i31_pkcs1_sign; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_pkcs1_vrfy.c b/src/tls/bearssl/rsa_default_pkcs1_vrfy.c deleted file mode 100644 index 75761ae62..000000000 --- a/src/tls/bearssl/rsa_default_pkcs1_vrfy.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_vrfy -br_rsa_pkcs1_vrfy_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_pkcs1_vrfy; -#elif BR_LOMUL - return &br_rsa_i15_pkcs1_vrfy; -#else - return &br_rsa_i31_pkcs1_vrfy; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_priv.c b/src/tls/bearssl/rsa_default_priv.c deleted file mode 100644 index cba2d6252..000000000 --- a/src/tls/bearssl/rsa_default_priv.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_private -br_rsa_private_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_private; -#elif BR_LOMUL - return &br_rsa_i15_private; -#else - return &br_rsa_i31_private; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_privexp.c b/src/tls/bearssl/rsa_default_privexp.c deleted file mode 100644 index f6441ec27..000000000 --- a/src/tls/bearssl/rsa_default_privexp.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_compute_privexp -br_rsa_compute_privexp_get_default(void) -{ -#if BR_LOMUL - return &br_rsa_i15_compute_privexp; -#else - return &br_rsa_i31_compute_privexp; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_pub.c b/src/tls/bearssl/rsa_default_pub.c deleted file mode 100644 index 2a88efba7..000000000 --- a/src/tls/bearssl/rsa_default_pub.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_public -br_rsa_public_get_default(void) -{ -#if BR_INT128 || BR_UMUL128 - return &br_rsa_i62_public; -#elif BR_LOMUL - return &br_rsa_i15_public; -#else - return &br_rsa_i31_public; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_default_pubexp.c b/src/tls/bearssl/rsa_default_pubexp.c deleted file mode 100644 index 63f05ec15..000000000 --- a/src/tls/bearssl/rsa_default_pubexp.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -br_rsa_compute_pubexp -br_rsa_compute_pubexp_get_default(void) -{ -#if BR_LOMUL - return &br_rsa_i15_compute_pubexp; -#else - return &br_rsa_i31_compute_pubexp; -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_keygen.c b/src/tls/bearssl/rsa_i15_keygen.c deleted file mode 100644 index b602bd8a4..000000000 --- a/src/tls/bearssl/rsa_i15_keygen.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Make a random integer of the provided size. The size is encoded. - * The header word is untouched. - */ -static void -mkrand(const br_prng_class **rng, uint16_t *x, uint32_t esize) -{ - size_t u, len; - unsigned m; - - len = (esize + 15) >> 4; - (*rng)->generate(rng, x + 1, len * sizeof(uint16_t)); - for (u = 1; u < len; u ++) { - x[u] &= 0x7FFF; - } - m = esize & 15; - if (m == 0) { - x[len] &= 0x7FFF; - } else { - x[len] &= 0x7FFF >> (15 - m); - } -} - -/* - * This is the big-endian unsigned representation of the product of - * all small primes from 13 to 1481. - */ -static const unsigned char SMALL_PRIMES[] = { - 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A, - 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7, - 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37, - 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5, - 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E, - 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6, - 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C, - 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40, - 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50, - 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7, - 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3, - 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E, - 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC, - 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08, - 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B, - 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22, - 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77, - 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E, - 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80, - 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8, - 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2, - 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC, - 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54, - 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74, - 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C, - 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD -}; - -/* - * We need temporary values for at least 7 integers of the same size - * as a factor (including header word); more space helps with performance - * (in modular exponentiations), but we much prefer to remain under - * 2 kilobytes in total, to save stack space. The macro TEMPS below - * exceeds 1024 (which is a count in 16-bit words) when BR_MAX_RSA_SIZE - * is greater than 4350 (default value is 4096, so the 2-kB limit is - * maintained unless BR_MAX_RSA_SIZE was modified). - */ -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#define TEMPS MAX(1024, 7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 29) / 15)) - -/* - * Perform trial division on a candidate prime. This computes - * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The - * br_i15_moddiv() function will report an error if y is not invertible - * modulo x. Returned value is 1 on success (none of the small primes - * divides x), 0 on error (a non-trivial GCD is obtained). - * - * This function assumes that x is odd. - */ -static uint32_t -trial_divisions(const uint16_t *x, uint16_t *t) -{ - uint16_t *y; - uint16_t x0i; - - y = t; - t += 1 + ((x[0] + 15) >> 4); - x0i = br_i15_ninv15(x[1]); - br_i15_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x); - return br_i15_moddiv(y, y, x, x0i, t); -} - -/* - * Perform n rounds of Miller-Rabin on the candidate prime x. This - * function assumes that x = 3 mod 4. - * - * Returned value is 1 on success (all rounds completed successfully), - * 0 otherwise. - */ -static uint32_t -miller_rabin(const br_prng_class **rng, const uint16_t *x, int n, - uint16_t *t, size_t tlen) -{ - /* - * Since x = 3 mod 4, the Miller-Rabin test is simple: - * - get a random base a (such that 1 < a < x-1) - * - compute z = a^((x-1)/2) mod x - * - if z != 1 and z != x-1, the number x is composite - * - * We generate bases 'a' randomly with a size which is - * one bit less than x, which ensures that a < x-1. It - * is not useful to verify that a > 1 because the probability - * that we get a value a equal to 0 or 1 is much smaller - * than the probability of our Miller-Rabin tests not to - * detect a composite, which is already quite smaller than the - * probability of the hardware misbehaving and return a - * composite integer because of some glitch (e.g. bad RAM - * or ill-timed cosmic ray). - */ - unsigned char *xm1d2; - size_t xlen, xm1d2_len, xm1d2_len_u16, u; - uint32_t asize; - unsigned cc; - uint16_t x0i; - - /* - * Compute (x-1)/2 (encoded). - */ - xm1d2 = (unsigned char *)t; - xm1d2_len = ((x[0] - (x[0] >> 4)) + 7) >> 3; - br_i15_encode(xm1d2, xm1d2_len, x); - cc = 0; - for (u = 0; u < xm1d2_len; u ++) { - unsigned w; - - w = xm1d2[u]; - xm1d2[u] = (unsigned char)((w >> 1) | cc); - cc = w << 7; - } - - /* - * We used some words of the provided buffer for (x-1)/2. - */ - xm1d2_len_u16 = (xm1d2_len + 1) >> 1; - t += xm1d2_len_u16; - tlen -= xm1d2_len_u16; - - xlen = (x[0] + 15) >> 4; - asize = x[0] - 1 - EQ0(x[0] & 15); - x0i = br_i15_ninv15(x[1]); - while (n -- > 0) { - uint16_t *a; - uint32_t eq1, eqm1; - - /* - * Generate a random base. We don't need the base to be - * really uniform modulo x, so we just get a random - * number which is one bit shorter than x. - */ - a = t; - a[0] = x[0]; - a[xlen] = 0; - mkrand(rng, a, asize); - - /* - * Compute a^((x-1)/2) mod x. We assume here that the - * function will not fail (the temporary array is large - * enough). - */ - br_i15_modpow_opt(a, xm1d2, xm1d2_len, - x, x0i, t + 1 + xlen, tlen - 1 - xlen); - - /* - * We must obtain either 1 or x-1. Note that x is odd, - * hence x-1 differs from x only in its low word (no - * carry). - */ - eq1 = a[1] ^ 1; - eqm1 = a[1] ^ (x[1] - 1); - for (u = 2; u <= xlen; u ++) { - eq1 |= a[u]; - eqm1 |= a[u] ^ x[u]; - } - - if ((EQ0(eq1) | EQ0(eqm1)) == 0) { - return 0; - } - } - return 1; -} - -/* - * Create a random prime of the provided size. 'size' is the _encoded_ - * bit length. The two top bits and the two bottom bits are set to 1. - */ -static void -mkprime(const br_prng_class **rng, uint16_t *x, uint32_t esize, - uint32_t pubexp, uint16_t *t, size_t tlen) -{ - size_t len; - - x[0] = esize; - len = (esize + 15) >> 4; - for (;;) { - size_t u; - uint32_t m3, m5, m7, m11; - int rounds; - - /* - * Generate random bits. We force the two top bits and the - * two bottom bits to 1. - */ - mkrand(rng, x, esize); - if ((esize & 15) == 0) { - x[len] |= 0x6000; - } else if ((esize & 15) == 1) { - x[len] |= 0x0001; - x[len - 1] |= 0x4000; - } else { - x[len] |= 0x0003 << ((esize & 15) - 2); - } - x[1] |= 0x0003; - - /* - * Trial division with low primes (3, 5, 7 and 11). We - * use the following properties: - * - * 2^2 = 1 mod 3 - * 2^4 = 1 mod 5 - * 2^3 = 1 mod 7 - * 2^10 = 1 mod 11 - */ - m3 = 0; - m5 = 0; - m7 = 0; - m11 = 0; - for (u = 0; u < len; u ++) { - uint32_t w; - - w = x[1 + u]; - m3 += w << (u & 1); - m3 = (m3 & 0xFF) + (m3 >> 8); - m5 += w << ((4 - u) & 3); - m5 = (m5 & 0xFF) + (m5 >> 8); - m7 += w; - m7 = (m7 & 0x1FF) + (m7 >> 9); - m11 += w << (5 & -(u & 1)); - m11 = (m11 & 0x3FF) + (m11 >> 10); - } - - /* - * Maximum values of m* at this point: - * m3: 511 - * m5: 2310 - * m7: 510 - * m11: 2047 - * We use the same properties to make further reductions. - */ - - m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 46 */ - m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 16 */ - m3 = ((m3 * 43) >> 5) & 3; - - m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 263 */ - m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 30 */ - m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 15 */ - m5 -= 10 & -GT(m5, 9); - m5 -= 5 & -GT(m5, 4); - - m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 69 */ - m7 = (m7 & 7) + (m7 >> 3); /* max: 14 */ - m7 = ((m7 * 147) >> 7) & 7; - - /* - * 2^5 = 32 = -1 mod 11. - */ - m11 = (m11 & 0x1F) + 66 - (m11 >> 5); /* max: 97 */ - m11 -= 88 & -GT(m11, 87); - m11 -= 44 & -GT(m11, 43); - m11 -= 22 & -GT(m11, 21); - m11 -= 11 & -GT(m11, 10); - - /* - * If any of these modulo is 0, then the candidate is - * not prime. Also, if pubexp is 3, 5, 7 or 11, and the - * corresponding modulus is 1, then the candidate must - * be rejected, because we need e to be invertible - * modulo p-1. We can use simple comparisons here - * because they won't leak information on a candidate - * that we keep, only on one that we reject (and is thus - * not secret). - */ - if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) { - continue; - } - if ((pubexp == 3 && m3 == 1) - || (pubexp == 5 && m5 == 5) - || (pubexp == 7 && m5 == 7) - || (pubexp == 11 && m5 == 11)) - { - continue; - } - - /* - * More trial divisions. - */ - if (!trial_divisions(x, t)) { - continue; - } - - /* - * Miller-Rabin algorithm. Since we selected a random - * integer, not a maliciously crafted integer, we can use - * relatively few rounds to lower the risk of a false - * positive (i.e. declaring prime a non-prime) under - * 2^(-80). It is not useful to lower the probability much - * below that, since that would be substantially below - * the probability of the hardware misbehaving. Sufficient - * numbers of rounds are extracted from the Handbook of - * Applied Cryptography, note 4.49 (page 149). - * - * Since we work on the encoded size (esize), we need to - * compare with encoded thresholds. - */ - if (esize < 320) { - rounds = 12; - } else if (esize < 480) { - rounds = 9; - } else if (esize < 693) { - rounds = 6; - } else if (esize < 906) { - rounds = 4; - } else if (esize < 1386) { - rounds = 3; - } else { - rounds = 2; - } - - if (miller_rabin(rng, x, rounds, t, tlen)) { - return; - } - } -} - -/* - * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided - * as parameter (with announced bit length equal to that of p). This - * function computes d = 1/e mod p-1 (for an odd integer e). Returned - * value is 1 on success, 0 on error (an error is reported if e is not - * invertible modulo p-1). - * - * The temporary buffer (t) must have room for at least 4 integers of - * the size of p. - */ -static uint32_t -invert_pubexp(uint16_t *d, const uint16_t *m, uint32_t e, uint16_t *t) -{ - uint16_t *f; - uint32_t r; - - f = t; - t += 1 + ((m[0] + 15) >> 4); - - /* - * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd. - */ - br_i15_zero(d, m[0]); - d[1] = 1; - br_i15_zero(f, m[0]); - f[1] = e & 0x7FFF; - f[2] = (e >> 15) & 0x7FFF; - f[3] = e >> 30; - r = br_i15_moddiv(d, f, m, br_i15_ninv15(m[1]), t); - - /* - * We really want d = 1/e mod p-1, with p = 2m. By the CRT, - * the result is either the d we got, or d + m. - * - * Let's write e*d = 1 + k*m, for some integer k. Integers e - * and m are odd. If d is odd, then e*d is odd, which implies - * that k must be even; in that case, e*d = 1 + (k/2)*2m, and - * thus d is already fine. Conversely, if d is even, then k - * is odd, and we must add m to d in order to get the correct - * result. - */ - br_i15_add(d, m, (uint32_t)(1 - (d[1] & 1))); - - return r; -} - -/* - * Swap two buffers in RAM. They must be disjoint. - */ -static void -bufswap(void *b1, void *b2, size_t len) -{ - size_t u; - unsigned char *buf1, *buf2; - - buf1 = b1; - buf2 = b2; - for (u = 0; u < len; u ++) { - unsigned w; - - w = buf1[u]; - buf1[u] = buf2[u]; - buf2[u] = w; - } -} - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_keygen(const br_prng_class **rng, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp) -{ - uint32_t esize_p, esize_q; - size_t plen, qlen, tlen; - uint16_t *p, *q, *t; - uint16_t tmp[TEMPS]; - uint32_t r; - - if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) { - return 0; - } - if (pubexp == 0) { - pubexp = 3; - } else if (pubexp == 1 || (pubexp & 1) == 0) { - return 0; - } - - esize_p = (size + 1) >> 1; - esize_q = size - esize_p; - sk->n_bitlen = size; - sk->p = kbuf_priv; - sk->plen = (esize_p + 7) >> 3; - sk->q = sk->p + sk->plen; - sk->qlen = (esize_q + 7) >> 3; - sk->dp = sk->q + sk->qlen; - sk->dplen = sk->plen; - sk->dq = sk->dp + sk->dplen; - sk->dqlen = sk->qlen; - sk->iq = sk->dq + sk->dqlen; - sk->iqlen = sk->plen; - - if (pk != NULL) { - pk->n = kbuf_pub; - pk->nlen = (size + 7) >> 3; - pk->e = pk->n + pk->nlen; - pk->elen = 4; - br_enc32be(pk->e, pubexp); - while (*pk->e == 0) { - pk->e ++; - pk->elen --; - } - } - - /* - * We now switch to encoded sizes. - * - * floor((x * 17477) / (2^18)) is equal to floor(x/15) for all - * integers x from 0 to 23833. - */ - esize_p += MUL15(esize_p, 17477) >> 18; - esize_q += MUL15(esize_q, 17477) >> 18; - plen = (esize_p + 15) >> 4; - qlen = (esize_q + 15) >> 4; - p = tmp; - q = p + 1 + plen; - t = q + 1 + qlen; - tlen = ((sizeof tmp) / sizeof(uint16_t)) - (2 + plen + qlen); - - /* - * When looking for primes p and q, we temporarily divide - * candidates by 2, in order to compute the inverse of the - * public exponent. - */ - - for (;;) { - mkprime(rng, p, esize_p, pubexp, t, tlen); - br_i15_rshift(p, 1); - if (invert_pubexp(t, p, pubexp, t + 1 + plen)) { - br_i15_add(p, p, 1); - p[1] |= 1; - br_i15_encode(sk->p, sk->plen, p); - br_i15_encode(sk->dp, sk->dplen, t); - break; - } - } - - for (;;) { - mkprime(rng, q, esize_q, pubexp, t, tlen); - br_i15_rshift(q, 1); - if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) { - br_i15_add(q, q, 1); - q[1] |= 1; - br_i15_encode(sk->q, sk->qlen, q); - br_i15_encode(sk->dq, sk->dqlen, t); - break; - } - } - - /* - * If p and q have the same size, then it is possible that q > p - * (when the target modulus size is odd, we generate p with a - * greater bit length than q). If q > p, we want to swap p and q - * (and also dp and dq) for two reasons: - * - The final step below (inversion of q modulo p) is easier if - * p > q. - * - While BearSSL's RSA code is perfectly happy with RSA keys such - * that p < q, some other implementations have restrictions and - * require p > q. - * - * Note that we can do a simple non-constant-time swap here, - * because the only information we leak here is that we insist on - * returning p and q such that p > q, which is not a secret. - */ - if (esize_p == esize_q && br_i15_sub(p, q, 0) == 1) { - bufswap(p, q, (1 + plen) * sizeof *p); - bufswap(sk->p, sk->q, sk->plen); - bufswap(sk->dp, sk->dq, sk->dplen); - } - - /* - * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p. - * - * We ensured that p >= q, so this is just a matter of updating the - * header word for q (and possibly adding an extra word). - * - * Theoretically, the call below may fail, in case we were - * extraordinarily unlucky, and p = q. Another failure case is if - * Miller-Rabin failed us _twice_, and p and q are non-prime and - * have a factor is common. We report the error mostly because it - * is cheap and we can, but in practice this never happens (or, at - * least, it happens way less often than hardware glitches). - */ - q[0] = p[0]; - if (plen > qlen) { - q[plen] = 0; - t ++; - tlen --; - } - br_i15_zero(t, p[0]); - t[1] = 1; - r = br_i15_moddiv(t, q, p, br_i15_ninv15(p[1]), t + 1 + plen); - br_i15_encode(sk->iq, sk->iqlen, t); - - /* - * Compute the public modulus too, if required. - */ - if (pk != NULL) { - br_i15_zero(t, p[0]); - br_i15_mulacc(t, p, q); - br_i15_encode(pk->n, pk->nlen, t); - } - - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_modulus.c b/src/tls/bearssl/rsa_i15_modulus.c deleted file mode 100644 index 3f572fbdc..000000000 --- a/src/tls/bearssl/rsa_i15_modulus.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk) -{ - uint16_t tmp[2 * ((BR_MAX_RSA_SIZE + 14) / 15) + 5]; - uint16_t *t, *p, *q; - const unsigned char *pbuf, *qbuf; - size_t nlen, plen, qlen, tlen; - - /* - * Compute actual byte and lengths for p and q. - */ - pbuf = sk->p; - plen = sk->plen; - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - qbuf = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *qbuf == 0) { - qbuf ++; - qlen --; - } - - t = tmp; - tlen = (sizeof tmp) / (sizeof tmp[0]); - - /* - * Decode p. - */ - if ((15 * tlen) < (plen << 3) + 15) { - return 0; - } - br_i15_decode(t, pbuf, plen); - p = t; - plen = (p[0] + 31) >> 4; - t += plen; - tlen -= plen; - - /* - * Decode q. - */ - if ((15 * tlen) < (qlen << 3) + 15) { - return 0; - } - br_i15_decode(t, qbuf, qlen); - q = t; - qlen = (q[0] + 31) >> 4; - t += qlen; - tlen -= qlen; - - /* - * Computation can proceed only if we have enough room for the - * modulus. - */ - if (tlen < (plen + qlen + 1)) { - return 0; - } - - /* - * Private key already contains the modulus bit length, from which - * we can infer the output length. Even if n is NULL, we still had - * to decode p and q to make sure that the product can be computed. - */ - nlen = (sk->n_bitlen + 7) >> 3; - if (n != NULL) { - br_i15_zero(t, p[0]); - br_i15_mulacc(t, p, q); - br_i15_encode(n, nlen, t); - } - return nlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_oaep_decrypt.c b/src/tls/bearssl/rsa_i15_oaep_decrypt.c deleted file mode 100644 index dd578797f..000000000 --- a/src/tls/bearssl/rsa_i15_oaep_decrypt.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_oaep_decrypt(const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len) -{ - uint32_t r; - - if (*len != ((sk->n_bitlen + 7) >> 3)) { - return 0; - } - r = br_rsa_i15_private(data, sk); - r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_oaep_encrypt.c b/src/tls/bearssl/rsa_i15_oaep_encrypt.c deleted file mode 100644 index 6a3bb53f5..000000000 --- a/src/tls/bearssl/rsa_i15_oaep_encrypt.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i15_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len) -{ - size_t dlen; - - dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, - pk, dst, dst_max_len, src, src_len); - if (dlen == 0) { - return 0; - } - return dlen & -(size_t)br_rsa_i15_public(dst, dlen, pk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_pkcs1_sign.c b/src/tls/bearssl/rsa_i15_pkcs1_sign.c deleted file mode 100644 index d4ef09fd6..000000000 --- a/src/tls/bearssl/rsa_i15_pkcs1_sign.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x) -{ - if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { - return 0; - } - return br_rsa_i15_private(x, sk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_pkcs1_vrfy.c b/src/tls/bearssl/rsa_i15_pkcs1_vrfy.c deleted file mode 100644 index 840cc440a..000000000 --- a/src/tls/bearssl/rsa_i15_pkcs1_vrfy.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out) -{ - unsigned char sig[BR_MAX_RSA_SIZE >> 3]; - - if (xlen > (sizeof sig)) { - return 0; - } - memcpy(sig, x, xlen); - if (!br_rsa_i15_public(sig, xlen, pk)) { - return 0; - } - return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_priv.c b/src/tls/bearssl/rsa_i15_priv.c deleted file mode 100644 index 1c50fba88..000000000 --- a/src/tls/bearssl/rsa_i15_priv.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15)) -#define TLEN (8 * U) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk) -{ - const unsigned char *p, *q; - size_t plen, qlen; - size_t fwlen; - uint16_t p0i, q0i; - size_t xlen, u; - uint16_t tmp[1 + TLEN]; - long z; - uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; - uint32_t r; - - /* - * Compute the actual lengths of p and q, in bytes. - * These lengths are not considered secret (we cannot really hide - * them anyway in constant-time code). - */ - p = sk->p; - plen = sk->plen; - while (plen > 0 && *p == 0) { - p ++; - plen --; - } - q = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *q == 0) { - q ++; - qlen --; - } - - /* - * Compute the maximum factor length, in words. - */ - z = (long)(plen > qlen ? plen : qlen) << 3; - fwlen = 1; - while (z > 0) { - z -= 15; - fwlen ++; - } - /* - * Round up the word length to an even number. - */ - fwlen += (fwlen & 1); - - /* - * We need to fit at least 6 values in the stack buffer. - */ - if (6 * fwlen > TLEN) { - return 0; - } - - /* - * Compute signature length (in bytes). - */ - xlen = (sk->n_bitlen + 7) >> 3; - - /* - * Ensure 32-bit alignment for value words. - */ - mq = tmp; - if (((uintptr_t)mq & 2) == 0) { - mq ++; - } - - /* - * Decode q. - */ - br_i15_decode(mq, q, qlen); - - /* - * Decode p. - */ - t1 = mq + fwlen; - br_i15_decode(t1, p, plen); - - /* - * Compute the modulus (product of the two factors), to compare - * it with the source value. We use br_i15_mulacc(), since it's - * already used later on. - */ - t2 = mq + 2 * fwlen; - br_i15_zero(t2, mq[0]); - br_i15_mulacc(t2, mq, t1); - - /* - * We encode the modulus into bytes, to perform the comparison - * with bytes. We know that the product length, in bytes, is - * exactly xlen. - * The comparison actually computes the carry when subtracting - * the modulus from the source value; that carry must be 1 for - * a value in the correct range. We keep it in r, which is our - * accumulator for the error code. - */ - t3 = mq + 4 * fwlen; - br_i15_encode(t3, xlen, t2); - u = xlen; - r = 0; - while (u > 0) { - uint32_t wn, wx; - - u --; - wn = ((unsigned char *)t3)[u]; - wx = x[u]; - r = ((wx - (wn + r)) >> 8) & 1; - } - - /* - * Move the decoded p to another temporary buffer. - */ - mp = mq + 2 * fwlen; - memmove(mp, t1, fwlen * sizeof *t1); - - /* - * Compute s2 = x^dq mod q. - */ - q0i = br_i15_ninv15(mq[1]); - s2 = mq + fwlen; - br_i15_decode_reduce(s2, x, xlen, mq); - r &= br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, - mq + 3 * fwlen, TLEN - 3 * fwlen); - - /* - * Compute s1 = x^dq mod q. - */ - p0i = br_i15_ninv15(mp[1]); - s1 = mq + 3 * fwlen; - br_i15_decode_reduce(s1, x, xlen, mp); - r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, - mq + 4 * fwlen, TLEN - 4 * fwlen); - - /* - * Compute: - * h = (s1 - s2)*(1/q) mod p - * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is - * unclear about whether p may be lower than q (some existing, - * widely deployed implementations of RSA don't tolerate p < q), - * but we want to support that occurrence, so we need to use the - * reduction function. - * - * Since we use br_i15_decode_reduce() for iq (purportedly, the - * inverse of q modulo p), we also tolerate improperly large - * values for this parameter. - */ - t1 = mq + 4 * fwlen; - t2 = mq + 5 * fwlen; - br_i15_reduce(t2, s2, mp); - br_i15_add(s1, mp, br_i15_sub(s1, t2, 1)); - br_i15_to_monty(s1, mp); - br_i15_decode_reduce(t1, sk->iq, sk->iqlen, mp); - br_i15_montymul(t2, s1, t1, mp, p0i); - - /* - * h is now in t2. We compute the final result: - * s = s2 + q*h - * All these operations are non-modular. - * - * We need mq, s2 and t2. We use the t3 buffer as destination. - * The buffers mp, s1 and t1 are no longer needed, so we can - * reuse them for t3. Moreover, the first step of the computation - * is to copy s2 into t3, after which s2 is not needed. Right - * now, mq is in slot 0, s2 is in slot 1, and t2 in slot 5. - * Therefore, we have ample room for t3 by simply using s2. - */ - t3 = s2; - br_i15_mulacc(t3, mq, t2); - - /* - * Encode the result. Since we already checked the value of xlen, - * we can just use it right away. - */ - br_i15_encode(x, xlen, t3); - - /* - * The only error conditions remaining at that point are invalid - * values for p and q (even integers). - */ - return p0i & q0i & r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_privexp.c b/src/tls/bearssl/rsa_i15_privexp.c deleted file mode 100644 index ec740b357..000000000 --- a/src/tls/bearssl/rsa_i15_privexp.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i15_compute_privexp(void *d, - const br_rsa_private_key *sk, uint32_t e) -{ - /* - * We want to invert e modulo phi = (p-1)(q-1). This first - * requires computing phi, which is easy since we have the factors - * p and q in the private key structure. - * - * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer. - * We could invert e modulo phi/4 then patch the result to - * modulo phi, but this would involve assembling three modulus-wide - * values (phi/4, 1 and e) and calling moddiv, that requires - * three more temporaries, for a total of six big integers, or - * slightly more than 3 kB of stack space for RSA-4096. This - * exceeds our stack requirements. - * - * Instead, we first use one step of the extended GCD: - * - * - We compute phi = k*e + r (Euclidean division of phi by e). - * If public exponent e is correct, then r != 0 (e must be - * invertible modulo phi). We also have k != 0 since we - * enforce non-ridiculously-small factors. - * - * - We find small u, v such that u*e - v*r = 1 (using a - * binary GCD; we can arrange for u < r and v < e, i.e. all - * values fit on 32 bits). - * - * - Solution is: d = u + v*k - * This last computation is exact: since u < r and v < e, - * the above implies d < r + e*((phi-r)/e) = phi - */ - - uint16_t tmp[4 * ((BR_MAX_RSA_FACTOR + 14) / 15) + 12]; - uint16_t *p, *q, *k, *m, *z, *phi; - const unsigned char *pbuf, *qbuf; - size_t plen, qlen, u, len, dlen; - uint32_t r, a, b, u0, v0, u1, v1, he, hr; - int i; - - /* - * Check that e is correct. - */ - if (e < 3 || (e & 1) == 0) { - return 0; - } - - /* - * Check lengths of p and q, and that they are both odd. - */ - pbuf = sk->p; - plen = sk->plen; - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8) - || (pbuf[plen - 1] & 1) != 1) - { - return 0; - } - qbuf = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *qbuf == 0) { - qbuf ++; - qlen --; - } - if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8) - || (qbuf[qlen - 1] & 1) != 1) - { - return 0; - } - - /* - * Output length is that of the modulus. - */ - dlen = (sk->n_bitlen + 7) >> 3; - if (d == NULL) { - return dlen; - } - - p = tmp; - br_i15_decode(p, pbuf, plen); - plen = (p[0] + 15) >> 4; - q = p + 1 + plen; - br_i15_decode(q, qbuf, qlen); - qlen = (q[0] + 15) >> 4; - - /* - * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that - * we do not need anymore). The mulacc function sets the announced - * bit length of t to be the sum of the announced bit lengths of - * p-1 and q-1, which is usually exact but may overshoot by one 1 - * bit in some cases; we readjust it to its true length. - */ - p[1] --; - q[1] --; - phi = q + 1 + qlen; - br_i15_zero(phi, p[0]); - br_i15_mulacc(phi, p, q); - len = (phi[0] + 15) >> 4; - memmove(tmp, phi, (1 + len) * sizeof *phi); - phi = tmp; - phi[0] = br_i15_bit_length(phi + 1, len); - len = (phi[0] + 15) >> 4; - - /* - * Divide phi by public exponent e. The final remainder r must be - * non-zero (otherwise, the key is invalid). The quotient is k, - * which we write over phi, since we don't need phi after that. - */ - r = 0; - for (u = len; u >= 1; u --) { - /* - * Upon entry, r < e, and phi[u] < 2^15; hence, - * hi:lo < e*2^15. Thus, the produced word k[u] - * must be lower than 2^15, and the new remainder r - * is lower than e. - */ - uint32_t hi, lo; - - hi = r >> 17; - lo = (r << 15) + phi[u]; - phi[u] = br_divrem(hi, lo, e, &r); - } - if (r == 0) { - return 0; - } - k = phi; - - /* - * Compute u and v such that u*e - v*r = GCD(e,r). We use - * a binary GCD algorithm, with 6 extra integers a, b, - * u0, u1, v0 and v1. Initial values are: - * a = e u0 = 1 v0 = 0 - * b = r u1 = r v1 = e-1 - * The following invariants are maintained: - * a = u0*e - v0*r - * b = u1*e - v1*r - * 0 < a <= e - * 0 < b <= r - * 0 <= u0 <= r - * 0 <= v0 <= e - * 0 <= u1 <= r - * 0 <= v1 <= e - * - * At each iteration, we reduce either a or b by one bit, and - * adjust u0, u1, v0 and v1 to maintain the invariants: - * - if a is even, then a <- a/2 - * - otherwise, if b is even, then b <- b/2 - * - otherwise, if a > b, then a <- (a-b)/2 - * - otherwise, if b > a, then b <- (b-a)/2 - * Algorithm stops when a = b. At that point, the common value - * is the GCD of e and r; it must be 1 (otherwise, the private - * key or public exponent is not valid). The (u0,v0) or (u1,v1) - * pairs are the solution we are looking for. - * - * Since either a or b is reduced by at least 1 bit at each - * iteration, 62 iterations are enough to reach the end - * condition. - * - * To maintain the invariants, we must compute the same operations - * on the u* and v* values that we do on a and b: - * - When a is divided by 2, u0 and v0 must be divided by 2. - * - When b is divided by 2, u1 and v1 must be divided by 2. - * - When b is subtracted from a, u1 and v1 are subtracted from - * u0 and v0, respectively. - * - When a is subtracted from b, u0 and v0 are subtracted from - * u1 and v1, respectively. - * - * However, we want to keep the u* and v* values in their proper - * ranges. The following remarks apply: - * - * - When a is divided by 2, then a is even. Therefore: - * - * * If r is odd, then u0 and v0 must have the same parity; - * if they are both odd, then adding r to u0 and e to v0 - * makes them both even, and the division by 2 brings them - * back to the proper range. - * - * * If r is even, then u0 must be even; if v0 is odd, then - * adding r to u0 and e to v0 makes them both even, and the - * division by 2 brings them back to the proper range. - * - * Thus, all we need to do is to look at the parity of v0, - * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid - * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the - * division (r+1 does not overflow since r < e; and (e/2)+1 - * is equal to (e+1)/2 since e is odd). - * - * - When we subtract b from a, three cases may occur: - * - * * u1 <= u0 and v1 <= v0: just do the subtractions - * - * * u1 > u0 and v1 > v0: compute: - * (u0, v0) <- (u0 + r - u1, v0 + e - v1) - * - * * u1 <= u0 and v1 > v0: compute: - * (u0, v0) <- (u0 + r - u1, v0 + e - v1) - * - * The fourth case (u1 > u0 and v1 <= v0) is not possible - * because it would contradict "b < a" (which is the reason - * why we subtract b from a). - * - * The tricky case is the third one: from the equations, it - * seems that u0 may go out of range. However, the invariants - * and ranges of other values imply that, in that case, the - * new u0 does not actually exceed the range. - * - * We can thus handle the subtraction by adding (r,e) based - * solely on the comparison between v0 and v1. - */ - a = e; - b = r; - u0 = 1; - v0 = 0; - u1 = r; - v1 = e - 1; - hr = (r + 1) >> 1; - he = (e >> 1) + 1; - for (i = 0; i < 62; i ++) { - uint32_t oa, ob, agtb, bgta; - uint32_t sab, sba, da, db; - uint32_t ctl; - - oa = a & 1; /* 1 if a is odd */ - ob = b & 1; /* 1 if b is odd */ - agtb = GT(a, b); /* 1 if a > b */ - bgta = GT(b, a); /* 1 if b > a */ - - sab = oa & ob & agtb; /* 1 if a <- a-b */ - sba = oa & ob & bgta; /* 1 if b <- b-a */ - - /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */ - ctl = GT(v1, v0); - a -= b & -sab; - u0 -= (u1 - (r & -ctl)) & -sab; - v0 -= (v1 - (e & -ctl)) & -sab; - - /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */ - ctl = GT(v0, v1); - b -= a & -sba; - u1 -= (u0 - (r & -ctl)) & -sba; - v1 -= (v0 - (e & -ctl)) & -sba; - - da = NOT(oa) | sab; /* 1 if a <- a/2 */ - db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */ - - /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */ - ctl = v0 & 1; - a ^= (a ^ (a >> 1)) & -da; - u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da; - v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da; - - /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */ - ctl = v1 & 1; - b ^= (b ^ (b >> 1)) & -db; - u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db; - v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db; - } - - /* - * Check that the GCD is indeed 1. If not, then the key is invalid - * (and there's no harm in leaking that piece of information). - */ - if (a != 1) { - return 0; - } - - /* - * Now we have u0*e - v0*r = 1. Let's compute the result as: - * d = u0 + v0*k - * We still have k in the tmp[] array, and its announced bit - * length is that of phi. - */ - m = k + 1 + len; - m[0] = (2 << 4) + 2; /* bit length is 32 bits, encoded */ - m[1] = v0 & 0x7FFF; - m[2] = (v0 >> 15) & 0x7FFF; - m[3] = v0 >> 30; - z = m + 4; - br_i15_zero(z, k[0]); - z[1] = u0 & 0x7FFF; - z[2] = (u0 >> 15) & 0x7FFF; - z[3] = u0 >> 30; - br_i15_mulacc(z, k, m); - - /* - * Encode the result. - */ - br_i15_encode(d, dlen, z); - return dlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_pub.c b/src/tls/bearssl/rsa_i15_pub.c deleted file mode 100644 index ad07d409a..000000000 --- a/src/tls/bearssl/rsa_i15_pub.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * As a strict minimum, we need four buffers that can hold a - * modular integer. - */ -#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15))) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk) -{ - const unsigned char *n; - size_t nlen; - uint16_t tmp[1 + TLEN]; - uint16_t *m, *a, *t; - size_t fwlen; - long z; - uint16_t m0i; - uint32_t r; - - /* - * Get the actual length of the modulus, and see if it fits within - * our stack buffer. We also check that the length of x[] is valid. - */ - n = pk->n; - nlen = pk->nlen; - while (nlen > 0 && *n == 0) { - n ++; - nlen --; - } - if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { - return 0; - } - z = (long)nlen << 3; - fwlen = 1; - while (z > 0) { - z -= 15; - fwlen ++; - } - /* - * Round up length to an even number. - */ - fwlen += (fwlen & 1); - - /* - * The modulus gets decoded into m[]. - * The value to exponentiate goes into a[]. - * The temporaries for modular exponentiations are in t[]. - * - * We want the first value word of each integer to be aligned - * on a 32-bit boundary. - */ - m = tmp; - if (((uintptr_t)m & 2) == 0) { - m ++; - } - a = m + fwlen; - t = m + 2 * fwlen; - - /* - * Decode the modulus. - */ - br_i15_decode(m, n, nlen); - m0i = br_i15_ninv15(m[1]); - - /* - * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be - * an odd integer. - */ - r = m0i & 1; - - /* - * Decode x[] into a[]; we also check that its value is proper. - */ - r &= br_i15_decode_mod(a, x, xlen, m); - - /* - * Compute the modular exponentiation. - */ - br_i15_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen); - - /* - * Encode the result. - */ - br_i15_encode(x, xlen, a); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i15_pubexp.c b/src/tls/bearssl/rsa_i15_pubexp.c deleted file mode 100644 index 7a4434251..000000000 --- a/src/tls/bearssl/rsa_i15_pubexp.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Recompute public exponent, based on factor p and reduced private - * exponent dp. - */ -static uint32_t -get_pubexp(const unsigned char *pbuf, size_t plen, - const unsigned char *dpbuf, size_t dplen) -{ - /* - * dp is the inverse of e modulo p-1. If p = 3 mod 4, then - * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1; - * thus, dp must be odd. - * - * We compute the inverse of dp modulo (p-1)/2. This requires - * first reducing dp modulo (p-1)/2 (this can be done with a - * conditional subtract, no need to use the generic modular - * reduction function); then, we use moddiv. - */ - - uint16_t tmp[6 * ((BR_MAX_RSA_FACTOR + 29) / 15)]; - uint16_t *p, *dp, *x; - size_t len; - uint32_t e; - - /* - * Compute actual factor length (in bytes) and check that it fits - * under our size constraints. - */ - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) { - return 0; - } - - /* - * Compute actual reduced exponent length (in bytes) and check that - * it is not longer than p. - */ - while (dplen > 0 && *dpbuf == 0) { - dpbuf ++; - dplen --; - } - if (dplen > plen || dplen == 0 - || (dplen == plen && dpbuf[0] > pbuf[0])) - { - return 0; - } - - /* - * Verify that p = 3 mod 4 and that dp is odd. - */ - if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) { - return 0; - } - - /* - * Decode p and compute (p-1)/2. - */ - p = tmp; - br_i15_decode(p, pbuf, plen); - len = (p[0] + 31) >> 4; - br_i15_rshift(p, 1); - - /* - * Decode dp and make sure its announced bit length matches that of - * p (we already know that the size of dp, in bits, does not exceed - * the size of p, so we just have to copy the header word). - */ - dp = p + len; - memset(dp, 0, len * sizeof *dp); - br_i15_decode(dp, dpbuf, dplen); - dp[0] = p[0]; - - /* - * Subtract (p-1)/2 from dp if necessary. - */ - br_i15_sub(dp, p, NOT(br_i15_sub(dp, p, 0))); - - /* - * If another subtraction is needed, then this means that the - * value was invalid. We don't care to leak information about - * invalid keys. - */ - if (br_i15_sub(dp, p, 0) == 0) { - return 0; - } - - /* - * Invert dp modulo (p-1)/2. If the inversion fails, then the - * key value was invalid. - */ - x = dp + len; - br_i15_zero(x, p[0]); - x[1] = 1; - if (br_i15_moddiv(x, dp, p, br_i15_ninv15(p[1]), x + len) == 0) { - return 0; - } - - /* - * We now have an inverse. We must set it to zero (error) if its - * length is greater than 32 bits and/or if it is an even integer. - * Take care that the bit_length function returns an encoded - * bit length. - */ - e = (uint32_t)x[1] | ((uint32_t)x[2] << 15) | ((uint32_t)x[3] << 30); - e &= -LT(br_i15_bit_length(x + 1, len - 1), 35); - e &= -(e & 1); - return e; -} - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk) -{ - /* - * Get the public exponent from both p and q. This is the right - * exponent if we get twice the same value. - */ - uint32_t ep, eq; - - ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen); - eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen); - return ep & -EQ(ep, eq); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_keygen.c b/src/tls/bearssl/rsa_i31_keygen.c deleted file mode 100644 index ff60cbbb8..000000000 --- a/src/tls/bearssl/rsa_i31_keygen.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_keygen(const br_prng_class **rng, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp) -{ - return br_rsa_i31_keygen_inner(rng, - sk, kbuf_priv, pk, kbuf_pub, size, pubexp, - &br_i31_modpow_opt); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_keygen_inner.c b/src/tls/bearssl/rsa_i31_keygen_inner.c deleted file mode 100644 index 8ede237ec..000000000 --- a/src/tls/bearssl/rsa_i31_keygen_inner.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Make a random integer of the provided size. The size is encoded. - * The header word is untouched. - */ -static void -mkrand(const br_prng_class **rng, uint32_t *x, uint32_t esize) -{ - size_t u, len; - unsigned m; - - len = (esize + 31) >> 5; - (*rng)->generate(rng, x + 1, len * sizeof(uint32_t)); - for (u = 1; u < len; u ++) { - x[u] &= 0x7FFFFFFF; - } - m = esize & 31; - if (m == 0) { - x[len] &= 0x7FFFFFFF; - } else { - x[len] &= 0x7FFFFFFF >> (31 - m); - } -} - -/* - * This is the big-endian unsigned representation of the product of - * all small primes from 13 to 1481. - */ -static const unsigned char SMALL_PRIMES[] = { - 0x2E, 0xAB, 0x92, 0xD1, 0x8B, 0x12, 0x47, 0x31, 0x54, 0x0A, - 0x99, 0x5D, 0x25, 0x5E, 0xE2, 0x14, 0x96, 0x29, 0x1E, 0xB7, - 0x78, 0x70, 0xCC, 0x1F, 0xA5, 0xAB, 0x8D, 0x72, 0x11, 0x37, - 0xFB, 0xD8, 0x1E, 0x3F, 0x5B, 0x34, 0x30, 0x17, 0x8B, 0xE5, - 0x26, 0x28, 0x23, 0xA1, 0x8A, 0xA4, 0x29, 0xEA, 0xFD, 0x9E, - 0x39, 0x60, 0x8A, 0xF3, 0xB5, 0xA6, 0xEB, 0x3F, 0x02, 0xB6, - 0x16, 0xC3, 0x96, 0x9D, 0x38, 0xB0, 0x7D, 0x82, 0x87, 0x0C, - 0xF7, 0xBE, 0x24, 0xE5, 0x5F, 0x41, 0x04, 0x79, 0x76, 0x40, - 0xE7, 0x00, 0x22, 0x7E, 0xB5, 0x85, 0x7F, 0x8D, 0x01, 0x50, - 0xE9, 0xD3, 0x29, 0x42, 0x08, 0xB3, 0x51, 0x40, 0x7B, 0xD7, - 0x8D, 0xCC, 0x10, 0x01, 0x64, 0x59, 0x28, 0xB6, 0x53, 0xF3, - 0x50, 0x4E, 0xB1, 0xF2, 0x58, 0xCD, 0x6E, 0xF5, 0x56, 0x3E, - 0x66, 0x2F, 0xD7, 0x07, 0x7F, 0x52, 0x4C, 0x13, 0x24, 0xDC, - 0x8E, 0x8D, 0xCC, 0xED, 0x77, 0xC4, 0x21, 0xD2, 0xFD, 0x08, - 0xEA, 0xD7, 0xC0, 0x5C, 0x13, 0x82, 0x81, 0x31, 0x2F, 0x2B, - 0x08, 0xE4, 0x80, 0x04, 0x7A, 0x0C, 0x8A, 0x3C, 0xDC, 0x22, - 0xE4, 0x5A, 0x7A, 0xB0, 0x12, 0x5E, 0x4A, 0x76, 0x94, 0x77, - 0xC2, 0x0E, 0x92, 0xBA, 0x8A, 0xA0, 0x1F, 0x14, 0x51, 0x1E, - 0x66, 0x6C, 0x38, 0x03, 0x6C, 0xC7, 0x4A, 0x4B, 0x70, 0x80, - 0xAF, 0xCA, 0x84, 0x51, 0xD8, 0xD2, 0x26, 0x49, 0xF5, 0xA8, - 0x5E, 0x35, 0x4B, 0xAC, 0xCE, 0x29, 0x92, 0x33, 0xB7, 0xA2, - 0x69, 0x7D, 0x0C, 0xE0, 0x9C, 0xDB, 0x04, 0xD6, 0xB4, 0xBC, - 0x39, 0xD7, 0x7F, 0x9E, 0x9D, 0x78, 0x38, 0x7F, 0x51, 0x54, - 0x50, 0x8B, 0x9E, 0x9C, 0x03, 0x6C, 0xF5, 0x9D, 0x2C, 0x74, - 0x57, 0xF0, 0x27, 0x2A, 0xC3, 0x47, 0xCA, 0xB9, 0xD7, 0x5C, - 0xFF, 0xC2, 0xAC, 0x65, 0x4E, 0xBD -}; - -/* - * We need temporary values for at least 7 integers of the same size - * as a factor (including header word); more space helps with performance - * (in modular exponentiations), but we much prefer to remain under - * 2 kilobytes in total, to save stack space. The macro TEMPS below - * exceeds 512 (which is a count in 32-bit words) when BR_MAX_RSA_SIZE - * is greater than 4464 (default value is 4096, so the 2-kB limit is - * maintained unless BR_MAX_RSA_SIZE was modified). - */ -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#define ROUND2(x) ((((x) + 1) >> 1) << 1) - -#define TEMPS MAX(512, ROUND2(7 * ((((BR_MAX_RSA_SIZE + 1) >> 1) + 61) / 31))) - -/* - * Perform trial division on a candidate prime. This computes - * y = SMALL_PRIMES mod x, then tries to compute y/y mod x. The - * br_i31_moddiv() function will report an error if y is not invertible - * modulo x. Returned value is 1 on success (none of the small primes - * divides x), 0 on error (a non-trivial GCD is obtained). - * - * This function assumes that x is odd. - */ -static uint32_t -trial_divisions(const uint32_t *x, uint32_t *t) -{ - uint32_t *y; - uint32_t x0i; - - y = t; - t += 1 + ((x[0] + 31) >> 5); - x0i = br_i31_ninv31(x[1]); - br_i31_decode_reduce(y, SMALL_PRIMES, sizeof SMALL_PRIMES, x); - return br_i31_moddiv(y, y, x, x0i, t); -} - -/* - * Perform n rounds of Miller-Rabin on the candidate prime x. This - * function assumes that x = 3 mod 4. - * - * Returned value is 1 on success (all rounds completed successfully), - * 0 otherwise. - */ -static uint32_t -miller_rabin(const br_prng_class **rng, const uint32_t *x, int n, - uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31) -{ - /* - * Since x = 3 mod 4, the Miller-Rabin test is simple: - * - get a random base a (such that 1 < a < x-1) - * - compute z = a^((x-1)/2) mod x - * - if z != 1 and z != x-1, the number x is composite - * - * We generate bases 'a' randomly with a size which is - * one bit less than x, which ensures that a < x-1. It - * is not useful to verify that a > 1 because the probability - * that we get a value a equal to 0 or 1 is much smaller - * than the probability of our Miller-Rabin tests not to - * detect a composite, which is already quite smaller than the - * probability of the hardware misbehaving and return a - * composite integer because of some glitch (e.g. bad RAM - * or ill-timed cosmic ray). - */ - unsigned char *xm1d2; - size_t xlen, xm1d2_len, xm1d2_len_u32, u; - uint32_t asize; - unsigned cc; - uint32_t x0i; - - /* - * Compute (x-1)/2 (encoded). - */ - xm1d2 = (unsigned char *)t; - xm1d2_len = ((x[0] - (x[0] >> 5)) + 7) >> 3; - br_i31_encode(xm1d2, xm1d2_len, x); - cc = 0; - for (u = 0; u < xm1d2_len; u ++) { - unsigned w; - - w = xm1d2[u]; - xm1d2[u] = (unsigned char)((w >> 1) | cc); - cc = w << 7; - } - - /* - * We used some words of the provided buffer for (x-1)/2. - */ - xm1d2_len_u32 = (xm1d2_len + 3) >> 2; - t += xm1d2_len_u32; - tlen -= xm1d2_len_u32; - - xlen = (x[0] + 31) >> 5; - asize = x[0] - 1 - EQ0(x[0] & 31); - x0i = br_i31_ninv31(x[1]); - while (n -- > 0) { - uint32_t *a, *t2; - uint32_t eq1, eqm1; - size_t t2len; - - /* - * Generate a random base. We don't need the base to be - * really uniform modulo x, so we just get a random - * number which is one bit shorter than x. - */ - a = t; - a[0] = x[0]; - a[xlen] = 0; - mkrand(rng, a, asize); - - /* - * Compute a^((x-1)/2) mod x. We assume here that the - * function will not fail (the temporary array is large - * enough). - */ - t2 = t + 1 + xlen; - t2len = tlen - 1 - xlen; - if ((t2len & 1) != 0) { - /* - * Since the source array is 64-bit aligned and - * has an even number of elements (TEMPS), we - * can use the parity of the remaining length to - * detect and adjust alignment. - */ - t2 ++; - t2len --; - } - mp31(a, xm1d2, xm1d2_len, x, x0i, t2, t2len); - - /* - * We must obtain either 1 or x-1. Note that x is odd, - * hence x-1 differs from x only in its low word (no - * carry). - */ - eq1 = a[1] ^ 1; - eqm1 = a[1] ^ (x[1] - 1); - for (u = 2; u <= xlen; u ++) { - eq1 |= a[u]; - eqm1 |= a[u] ^ x[u]; - } - - if ((EQ0(eq1) | EQ0(eqm1)) == 0) { - return 0; - } - } - return 1; -} - -/* - * Create a random prime of the provided size. 'size' is the _encoded_ - * bit length. The two top bits and the two bottom bits are set to 1. - */ -static void -mkprime(const br_prng_class **rng, uint32_t *x, uint32_t esize, - uint32_t pubexp, uint32_t *t, size_t tlen, br_i31_modpow_opt_type mp31) -{ - size_t len; - - x[0] = esize; - len = (esize + 31) >> 5; - for (;;) { - size_t u; - uint32_t m3, m5, m7, m11; - int rounds, s7, s11; - - /* - * Generate random bits. We force the two top bits and the - * two bottom bits to 1. - */ - mkrand(rng, x, esize); - if ((esize & 31) == 0) { - x[len] |= 0x60000000; - } else if ((esize & 31) == 1) { - x[len] |= 0x00000001; - x[len - 1] |= 0x40000000; - } else { - x[len] |= 0x00000003 << ((esize & 31) - 2); - } - x[1] |= 0x00000003; - - /* - * Trial division with low primes (3, 5, 7 and 11). We - * use the following properties: - * - * 2^2 = 1 mod 3 - * 2^4 = 1 mod 5 - * 2^3 = 1 mod 7 - * 2^10 = 1 mod 11 - */ - m3 = 0; - m5 = 0; - m7 = 0; - m11 = 0; - s7 = 0; - s11 = 0; - for (u = 0; u < len; u ++) { - uint32_t w, w3, w5, w7, w11; - - w = x[1 + u]; - w3 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */ - w5 = (w & 0xFFFF) + (w >> 16); /* max: 98302 */ - w7 = (w & 0x7FFF) + (w >> 15); /* max: 98302 */ - w11 = (w & 0xFFFFF) + (w >> 20); /* max: 1050622 */ - - m3 += w3 << (u & 1); - m3 = (m3 & 0xFF) + (m3 >> 8); /* max: 1025 */ - - m5 += w5 << ((4 - u) & 3); - m5 = (m5 & 0xFFF) + (m5 >> 12); /* max: 4479 */ - - m7 += w7 << s7; - m7 = (m7 & 0x1FF) + (m7 >> 9); /* max: 1280 */ - if (++ s7 == 3) { - s7 = 0; - } - - m11 += w11 << s11; - if (++ s11 == 10) { - s11 = 0; - } - m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 526847 */ - } - - m3 = (m3 & 0x3F) + (m3 >> 6); /* max: 78 */ - m3 = (m3 & 0x0F) + (m3 >> 4); /* max: 18 */ - m3 = ((m3 * 43) >> 5) & 3; - - m5 = (m5 & 0xFF) + (m5 >> 8); /* max: 271 */ - m5 = (m5 & 0x0F) + (m5 >> 4); /* max: 31 */ - m5 -= 20 & -GT(m5, 19); - m5 -= 10 & -GT(m5, 9); - m5 -= 5 & -GT(m5, 4); - - m7 = (m7 & 0x3F) + (m7 >> 6); /* max: 82 */ - m7 = (m7 & 0x07) + (m7 >> 3); /* max: 16 */ - m7 = ((m7 * 147) >> 7) & 7; - - /* - * 2^5 = 32 = -1 mod 11. - */ - m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1536 */ - m11 = (m11 & 0x3FF) + (m11 >> 10); /* max: 1023 */ - m11 = (m11 & 0x1F) + 33 - (m11 >> 5); /* max: 64 */ - m11 -= 44 & -GT(m11, 43); - m11 -= 22 & -GT(m11, 21); - m11 -= 11 & -GT(m11, 10); - - /* - * If any of these modulo is 0, then the candidate is - * not prime. Also, if pubexp is 3, 5, 7 or 11, and the - * corresponding modulus is 1, then the candidate must - * be rejected, because we need e to be invertible - * modulo p-1. We can use simple comparisons here - * because they won't leak information on a candidate - * that we keep, only on one that we reject (and is thus - * not secret). - */ - if (m3 == 0 || m5 == 0 || m7 == 0 || m11 == 0) { - continue; - } - if ((pubexp == 3 && m3 == 1) - || (pubexp == 5 && m5 == 5) - || (pubexp == 7 && m5 == 7) - || (pubexp == 11 && m5 == 11)) - { - continue; - } - - /* - * More trial divisions. - */ - if (!trial_divisions(x, t)) { - continue; - } - - /* - * Miller-Rabin algorithm. Since we selected a random - * integer, not a maliciously crafted integer, we can use - * relatively few rounds to lower the risk of a false - * positive (i.e. declaring prime a non-prime) under - * 2^(-80). It is not useful to lower the probability much - * below that, since that would be substantially below - * the probability of the hardware misbehaving. Sufficient - * numbers of rounds are extracted from the Handbook of - * Applied Cryptography, note 4.49 (page 149). - * - * Since we work on the encoded size (esize), we need to - * compare with encoded thresholds. - */ - if (esize < 309) { - rounds = 12; - } else if (esize < 464) { - rounds = 9; - } else if (esize < 670) { - rounds = 6; - } else if (esize < 877) { - rounds = 4; - } else if (esize < 1341) { - rounds = 3; - } else { - rounds = 2; - } - - if (miller_rabin(rng, x, rounds, t, tlen, mp31)) { - return; - } - } -} - -/* - * Let p be a prime (p > 2^33, p = 3 mod 4). Let m = (p-1)/2, provided - * as parameter (with announced bit length equal to that of p). This - * function computes d = 1/e mod p-1 (for an odd integer e). Returned - * value is 1 on success, 0 on error (an error is reported if e is not - * invertible modulo p-1). - * - * The temporary buffer (t) must have room for at least 4 integers of - * the size of p. - */ -static uint32_t -invert_pubexp(uint32_t *d, const uint32_t *m, uint32_t e, uint32_t *t) -{ - uint32_t *f; - uint32_t r; - - f = t; - t += 1 + ((m[0] + 31) >> 5); - - /* - * Compute d = 1/e mod m. Since p = 3 mod 4, m is odd. - */ - br_i31_zero(d, m[0]); - d[1] = 1; - br_i31_zero(f, m[0]); - f[1] = e & 0x7FFFFFFF; - f[2] = e >> 31; - r = br_i31_moddiv(d, f, m, br_i31_ninv31(m[1]), t); - - /* - * We really want d = 1/e mod p-1, with p = 2m. By the CRT, - * the result is either the d we got, or d + m. - * - * Let's write e*d = 1 + k*m, for some integer k. Integers e - * and m are odd. If d is odd, then e*d is odd, which implies - * that k must be even; in that case, e*d = 1 + (k/2)*2m, and - * thus d is already fine. Conversely, if d is even, then k - * is odd, and we must add m to d in order to get the correct - * result. - */ - br_i31_add(d, m, (uint32_t)(1 - (d[1] & 1))); - - return r; -} - -/* - * Swap two buffers in RAM. They must be disjoint. - */ -static void -bufswap(void *b1, void *b2, size_t len) -{ - size_t u; - unsigned char *buf1, *buf2; - - buf1 = b1; - buf2 = b2; - for (u = 0; u < len; u ++) { - unsigned w; - - w = buf1[u]; - buf1[u] = buf2[u]; - buf2[u] = w; - } -} - -/* see inner.h */ -uint32_t -br_rsa_i31_keygen_inner(const br_prng_class **rng, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31) -{ - uint32_t esize_p, esize_q; - size_t plen, qlen, tlen; - uint32_t *p, *q, *t; - union { - uint32_t t32[TEMPS]; - uint64_t t64[TEMPS >> 1]; /* for 64-bit alignment */ - } tmp; - uint32_t r; - - if (size < BR_MIN_RSA_SIZE || size > BR_MAX_RSA_SIZE) { - return 0; - } - if (pubexp == 0) { - pubexp = 3; - } else if (pubexp == 1 || (pubexp & 1) == 0) { - return 0; - } - - esize_p = (size + 1) >> 1; - esize_q = size - esize_p; - sk->n_bitlen = size; - sk->p = kbuf_priv; - sk->plen = (esize_p + 7) >> 3; - sk->q = sk->p + sk->plen; - sk->qlen = (esize_q + 7) >> 3; - sk->dp = sk->q + sk->qlen; - sk->dplen = sk->plen; - sk->dq = sk->dp + sk->dplen; - sk->dqlen = sk->qlen; - sk->iq = sk->dq + sk->dqlen; - sk->iqlen = sk->plen; - - if (pk != NULL) { - pk->n = kbuf_pub; - pk->nlen = (size + 7) >> 3; - pk->e = pk->n + pk->nlen; - pk->elen = 4; - br_enc32be(pk->e, pubexp); - while (*pk->e == 0) { - pk->e ++; - pk->elen --; - } - } - - /* - * We now switch to encoded sizes. - * - * floor((x * 16913) / (2^19)) is equal to floor(x/31) for all - * integers x from 0 to 34966; the intermediate product fits on - * 30 bits, thus we can use MUL31(). - */ - esize_p += MUL31(esize_p, 16913) >> 19; - esize_q += MUL31(esize_q, 16913) >> 19; - plen = (esize_p + 31) >> 5; - qlen = (esize_q + 31) >> 5; - p = tmp.t32; - q = p + 1 + plen; - t = q + 1 + qlen; - tlen = ((sizeof tmp.t32) / sizeof(uint32_t)) - (2 + plen + qlen); - - /* - * When looking for primes p and q, we temporarily divide - * candidates by 2, in order to compute the inverse of the - * public exponent. - */ - - for (;;) { - mkprime(rng, p, esize_p, pubexp, t, tlen, mp31); - br_i31_rshift(p, 1); - if (invert_pubexp(t, p, pubexp, t + 1 + plen)) { - br_i31_add(p, p, 1); - p[1] |= 1; - br_i31_encode(sk->p, sk->plen, p); - br_i31_encode(sk->dp, sk->dplen, t); - break; - } - } - - for (;;) { - mkprime(rng, q, esize_q, pubexp, t, tlen, mp31); - br_i31_rshift(q, 1); - if (invert_pubexp(t, q, pubexp, t + 1 + qlen)) { - br_i31_add(q, q, 1); - q[1] |= 1; - br_i31_encode(sk->q, sk->qlen, q); - br_i31_encode(sk->dq, sk->dqlen, t); - break; - } - } - - /* - * If p and q have the same size, then it is possible that q > p - * (when the target modulus size is odd, we generate p with a - * greater bit length than q). If q > p, we want to swap p and q - * (and also dp and dq) for two reasons: - * - The final step below (inversion of q modulo p) is easier if - * p > q. - * - While BearSSL's RSA code is perfectly happy with RSA keys such - * that p < q, some other implementations have restrictions and - * require p > q. - * - * Note that we can do a simple non-constant-time swap here, - * because the only information we leak here is that we insist on - * returning p and q such that p > q, which is not a secret. - */ - if (esize_p == esize_q && br_i31_sub(p, q, 0) == 1) { - bufswap(p, q, (1 + plen) * sizeof *p); - bufswap(sk->p, sk->q, sk->plen); - bufswap(sk->dp, sk->dq, sk->dplen); - } - - /* - * We have produced p, q, dp and dq. We can now compute iq = 1/d mod p. - * - * We ensured that p >= q, so this is just a matter of updating the - * header word for q (and possibly adding an extra word). - * - * Theoretically, the call below may fail, in case we were - * extraordinarily unlucky, and p = q. Another failure case is if - * Miller-Rabin failed us _twice_, and p and q are non-prime and - * have a factor is common. We report the error mostly because it - * is cheap and we can, but in practice this never happens (or, at - * least, it happens way less often than hardware glitches). - */ - q[0] = p[0]; - if (plen > qlen) { - q[plen] = 0; - t ++; - tlen --; - } - br_i31_zero(t, p[0]); - t[1] = 1; - r = br_i31_moddiv(t, q, p, br_i31_ninv31(p[1]), t + 1 + plen); - br_i31_encode(sk->iq, sk->iqlen, t); - - /* - * Compute the public modulus too, if required. - */ - if (pk != NULL) { - br_i31_zero(t, p[0]); - br_i31_mulacc(t, p, q); - br_i31_encode(pk->n, pk->nlen, t); - } - - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_modulus.c b/src/tls/bearssl/rsa_i31_modulus.c deleted file mode 100644 index 1a98fdc07..000000000 --- a/src/tls/bearssl/rsa_i31_modulus.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk) -{ - uint32_t tmp[2 * ((BR_MAX_RSA_SIZE + 30) / 31) + 5]; - uint32_t *t, *p, *q; - const unsigned char *pbuf, *qbuf; - size_t nlen, plen, qlen, tlen; - - /* - * Compute actual byte and lengths for p and q. - */ - pbuf = sk->p; - plen = sk->plen; - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - qbuf = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *qbuf == 0) { - qbuf ++; - qlen --; - } - - t = tmp; - tlen = (sizeof tmp) / (sizeof tmp[0]); - - /* - * Decode p. - */ - if ((31 * tlen) < (plen << 3) + 31) { - return 0; - } - br_i31_decode(t, pbuf, plen); - p = t; - plen = (p[0] + 63) >> 5; - t += plen; - tlen -= plen; - - /* - * Decode q. - */ - if ((31 * tlen) < (qlen << 3) + 31) { - return 0; - } - br_i31_decode(t, qbuf, qlen); - q = t; - qlen = (q[0] + 63) >> 5; - t += qlen; - tlen -= qlen; - - /* - * Computation can proceed only if we have enough room for the - * modulus. - */ - if (tlen < (plen + qlen + 1)) { - return 0; - } - - /* - * Private key already contains the modulus bit length, from which - * we can infer the output length. Even if n is NULL, we still had - * to decode p and q to make sure that the product can be computed. - */ - nlen = (sk->n_bitlen + 7) >> 3; - if (n != NULL) { - br_i31_zero(t, p[0]); - br_i31_mulacc(t, p, q); - br_i31_encode(n, nlen, t); - } - return nlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_oaep_decrypt.c b/src/tls/bearssl/rsa_i31_oaep_decrypt.c deleted file mode 100644 index 5f9f2dee1..000000000 --- a/src/tls/bearssl/rsa_i31_oaep_decrypt.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_oaep_decrypt(const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len) -{ - uint32_t r; - - if (*len != ((sk->n_bitlen + 7) >> 3)) { - return 0; - } - r = br_rsa_i31_private(data, sk); - r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_oaep_encrypt.c b/src/tls/bearssl/rsa_i31_oaep_encrypt.c deleted file mode 100644 index 771463751..000000000 --- a/src/tls/bearssl/rsa_i31_oaep_encrypt.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i31_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len) -{ - size_t dlen; - - dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, - pk, dst, dst_max_len, src, src_len); - if (dlen == 0) { - return 0; - } - return dlen & -(size_t)br_rsa_i31_public(dst, dlen, pk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_pkcs1_sign.c b/src/tls/bearssl/rsa_i31_pkcs1_sign.c deleted file mode 100644 index 5b5766c1e..000000000 --- a/src/tls/bearssl/rsa_i31_pkcs1_sign.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x) -{ - if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { - return 0; - } - return br_rsa_i31_private(x, sk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_pkcs1_vrfy.c b/src/tls/bearssl/rsa_i31_pkcs1_vrfy.c deleted file mode 100644 index 0df7fbe27..000000000 --- a/src/tls/bearssl/rsa_i31_pkcs1_vrfy.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out) -{ - unsigned char sig[BR_MAX_RSA_SIZE >> 3]; - - if (xlen > (sizeof sig)) { - return 0; - } - memcpy(sig, x, xlen); - if (!br_rsa_i31_public(sig, xlen, pk)) { - return 0; - } - return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_priv.c b/src/tls/bearssl/rsa_i31_priv.c deleted file mode 100644 index 68d1d6743..000000000 --- a/src/tls/bearssl/rsa_i31_priv.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31)) -#define TLEN (8 * U) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_private(unsigned char *x, const br_rsa_private_key *sk) -{ - const unsigned char *p, *q; - size_t plen, qlen; - size_t fwlen; - uint32_t p0i, q0i; - size_t xlen, u; - uint32_t tmp[1 + TLEN]; - long z; - uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; - uint32_t r; - - /* - * Compute the actual lengths of p and q, in bytes. - * These lengths are not considered secret (we cannot really hide - * them anyway in constant-time code). - */ - p = sk->p; - plen = sk->plen; - while (plen > 0 && *p == 0) { - p ++; - plen --; - } - q = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *q == 0) { - q ++; - qlen --; - } - - /* - * Compute the maximum factor length, in words. - */ - z = (long)(plen > qlen ? plen : qlen) << 3; - fwlen = 1; - while (z > 0) { - z -= 31; - fwlen ++; - } - - /* - * Round up the word length to an even number. - */ - fwlen += (fwlen & 1); - - /* - * We need to fit at least 6 values in the stack buffer. - */ - if (6 * fwlen > TLEN) { - return 0; - } - - /* - * Compute modulus length (in bytes). - */ - xlen = (sk->n_bitlen + 7) >> 3; - - /* - * Decode q. - */ - mq = tmp; - br_i31_decode(mq, q, qlen); - - /* - * Decode p. - */ - t1 = mq + fwlen; - br_i31_decode(t1, p, plen); - - /* - * Compute the modulus (product of the two factors), to compare - * it with the source value. We use br_i31_mulacc(), since it's - * already used later on. - */ - t2 = mq + 2 * fwlen; - br_i31_zero(t2, mq[0]); - br_i31_mulacc(t2, mq, t1); - - /* - * We encode the modulus into bytes, to perform the comparison - * with bytes. We know that the product length, in bytes, is - * exactly xlen. - * The comparison actually computes the carry when subtracting - * the modulus from the source value; that carry must be 1 for - * a value in the correct range. We keep it in r, which is our - * accumulator for the error code. - */ - t3 = mq + 4 * fwlen; - br_i31_encode(t3, xlen, t2); - u = xlen; - r = 0; - while (u > 0) { - uint32_t wn, wx; - - u --; - wn = ((unsigned char *)t3)[u]; - wx = x[u]; - r = ((wx - (wn + r)) >> 8) & 1; - } - - /* - * Move the decoded p to another temporary buffer. - */ - mp = mq + 2 * fwlen; - memmove(mp, t1, fwlen * sizeof *t1); - - /* - * Compute s2 = x^dq mod q. - */ - q0i = br_i31_ninv31(mq[1]); - s2 = mq + fwlen; - br_i31_decode_reduce(s2, x, xlen, mq); - r &= br_i31_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, - mq + 3 * fwlen, TLEN - 3 * fwlen); - - /* - * Compute s1 = x^dp mod p. - */ - p0i = br_i31_ninv31(mp[1]); - s1 = mq + 3 * fwlen; - br_i31_decode_reduce(s1, x, xlen, mp); - r &= br_i31_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, - mq + 4 * fwlen, TLEN - 4 * fwlen); - - /* - * Compute: - * h = (s1 - s2)*(1/q) mod p - * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is - * unclear about whether p may be lower than q (some existing, - * widely deployed implementations of RSA don't tolerate p < q), - * but we want to support that occurrence, so we need to use the - * reduction function. - * - * Since we use br_i31_decode_reduce() for iq (purportedly, the - * inverse of q modulo p), we also tolerate improperly large - * values for this parameter. - */ - t1 = mq + 4 * fwlen; - t2 = mq + 5 * fwlen; - br_i31_reduce(t2, s2, mp); - br_i31_add(s1, mp, br_i31_sub(s1, t2, 1)); - br_i31_to_monty(s1, mp); - br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp); - br_i31_montymul(t2, s1, t1, mp, p0i); - - /* - * h is now in t2. We compute the final result: - * s = s2 + q*h - * All these operations are non-modular. - * - * We need mq, s2 and t2. We use the t3 buffer as destination. - * The buffers mp, s1 and t1 are no longer needed, so we can - * reuse them for t3. Moreover, the first step of the computation - * is to copy s2 into t3, after which s2 is not needed. Right - * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5. - * Therefore, we have ample room for t3 by simply using s2. - */ - t3 = s2; - br_i31_mulacc(t3, mq, t2); - - /* - * Encode the result. Since we already checked the value of xlen, - * we can just use it right away. - */ - br_i31_encode(x, xlen, t3); - - /* - * The only error conditions remaining at that point are invalid - * values for p and q (even integers). - */ - return p0i & q0i & r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_privexp.c b/src/tls/bearssl/rsa_i31_privexp.c deleted file mode 100644 index 563eb2dbe..000000000 --- a/src/tls/bearssl/rsa_i31_privexp.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i31_compute_privexp(void *d, - const br_rsa_private_key *sk, uint32_t e) -{ - /* - * We want to invert e modulo phi = (p-1)(q-1). This first - * requires computing phi, which is easy since we have the factors - * p and q in the private key structure. - * - * Since p = 3 mod 4 and q = 3 mod 4, phi/4 is an odd integer. - * We could invert e modulo phi/4 then patch the result to - * modulo phi, but this would involve assembling three modulus-wide - * values (phi/4, 1 and e) and calling moddiv, that requires - * three more temporaries, for a total of six big integers, or - * slightly more than 3 kB of stack space for RSA-4096. This - * exceeds our stack requirements. - * - * Instead, we first use one step of the extended GCD: - * - * - We compute phi = k*e + r (Euclidean division of phi by e). - * If public exponent e is correct, then r != 0 (e must be - * invertible modulo phi). We also have k != 0 since we - * enforce non-ridiculously-small factors. - * - * - We find small u, v such that u*e - v*r = 1 (using a - * binary GCD; we can arrange for u < r and v < e, i.e. all - * values fit on 32 bits). - * - * - Solution is: d = u + v*k - * This last computation is exact: since u < r and v < e, - * the above implies d < r + e*((phi-r)/e) = phi - */ - - uint32_t tmp[4 * ((BR_MAX_RSA_FACTOR + 30) / 31) + 12]; - uint32_t *p, *q, *k, *m, *z, *phi; - const unsigned char *pbuf, *qbuf; - size_t plen, qlen, u, len, dlen; - uint32_t r, a, b, u0, v0, u1, v1, he, hr; - int i; - - /* - * Check that e is correct. - */ - if (e < 3 || (e & 1) == 0) { - return 0; - } - - /* - * Check lengths of p and q, and that they are both odd. - */ - pbuf = sk->p; - plen = sk->plen; - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - if (plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8) - || (pbuf[plen - 1] & 1) != 1) - { - return 0; - } - qbuf = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *qbuf == 0) { - qbuf ++; - qlen --; - } - if (qlen < 5 || qlen > (BR_MAX_RSA_FACTOR / 8) - || (qbuf[qlen - 1] & 1) != 1) - { - return 0; - } - - /* - * Output length is that of the modulus. - */ - dlen = (sk->n_bitlen + 7) >> 3; - if (d == NULL) { - return dlen; - } - - p = tmp; - br_i31_decode(p, pbuf, plen); - plen = (p[0] + 31) >> 5; - q = p + 1 + plen; - br_i31_decode(q, qbuf, qlen); - qlen = (q[0] + 31) >> 5; - - /* - * Compute phi = (p-1)*(q-1), then move it over p-1 and q-1 (that - * we do not need anymore). The mulacc function sets the announced - * bit length of t to be the sum of the announced bit lengths of - * p-1 and q-1, which is usually exact but may overshoot by one 1 - * bit in some cases; we readjust it to its true length. - */ - p[1] --; - q[1] --; - phi = q + 1 + qlen; - br_i31_zero(phi, p[0]); - br_i31_mulacc(phi, p, q); - len = (phi[0] + 31) >> 5; - memmove(tmp, phi, (1 + len) * sizeof *phi); - phi = tmp; - phi[0] = br_i31_bit_length(phi + 1, len); - len = (phi[0] + 31) >> 5; - - /* - * Divide phi by public exponent e. The final remainder r must be - * non-zero (otherwise, the key is invalid). The quotient is k, - * which we write over phi, since we don't need phi after that. - */ - r = 0; - for (u = len; u >= 1; u --) { - /* - * Upon entry, r < e, and phi[u] < 2^31; hence, - * hi:lo < e*2^31. Thus, the produced word k[u] - * must be lower than 2^31, and the new remainder r - * is lower than e. - */ - uint32_t hi, lo; - - hi = r >> 1; - lo = (r << 31) + phi[u]; - phi[u] = br_divrem(hi, lo, e, &r); - } - if (r == 0) { - return 0; - } - k = phi; - - /* - * Compute u and v such that u*e - v*r = GCD(e,r). We use - * a binary GCD algorithm, with 6 extra integers a, b, - * u0, u1, v0 and v1. Initial values are: - * a = e u0 = 1 v0 = 0 - * b = r u1 = r v1 = e-1 - * The following invariants are maintained: - * a = u0*e - v0*r - * b = u1*e - v1*r - * 0 < a <= e - * 0 < b <= r - * 0 <= u0 <= r - * 0 <= v0 <= e - * 0 <= u1 <= r - * 0 <= v1 <= e - * - * At each iteration, we reduce either a or b by one bit, and - * adjust u0, u1, v0 and v1 to maintain the invariants: - * - if a is even, then a <- a/2 - * - otherwise, if b is even, then b <- b/2 - * - otherwise, if a > b, then a <- (a-b)/2 - * - otherwise, if b > a, then b <- (b-a)/2 - * Algorithm stops when a = b. At that point, the common value - * is the GCD of e and r; it must be 1 (otherwise, the private - * key or public exponent is not valid). The (u0,v0) or (u1,v1) - * pairs are the solution we are looking for. - * - * Since either a or b is reduced by at least 1 bit at each - * iteration, 62 iterations are enough to reach the end - * condition. - * - * To maintain the invariants, we must compute the same operations - * on the u* and v* values that we do on a and b: - * - When a is divided by 2, u0 and v0 must be divided by 2. - * - When b is divided by 2, u1 and v1 must be divided by 2. - * - When b is subtracted from a, u1 and v1 are subtracted from - * u0 and v0, respectively. - * - When a is subtracted from b, u0 and v0 are subtracted from - * u1 and v1, respectively. - * - * However, we want to keep the u* and v* values in their proper - * ranges. The following remarks apply: - * - * - When a is divided by 2, then a is even. Therefore: - * - * * If r is odd, then u0 and v0 must have the same parity; - * if they are both odd, then adding r to u0 and e to v0 - * makes them both even, and the division by 2 brings them - * back to the proper range. - * - * * If r is even, then u0 must be even; if v0 is odd, then - * adding r to u0 and e to v0 makes them both even, and the - * division by 2 brings them back to the proper range. - * - * Thus, all we need to do is to look at the parity of v0, - * and add (r,e) to (u0,v0) when v0 is odd. In order to avoid - * a 32-bit overflow, we can add ((r+1)/2,(e/2)+1) after the - * division (r+1 does not overflow since r < e; and (e/2)+1 - * is equal to (e+1)/2 since e is odd). - * - * - When we subtract b from a, three cases may occur: - * - * * u1 <= u0 and v1 <= v0: just do the subtractions - * - * * u1 > u0 and v1 > v0: compute: - * (u0, v0) <- (u0 + r - u1, v0 + e - v1) - * - * * u1 <= u0 and v1 > v0: compute: - * (u0, v0) <- (u0 + r - u1, v0 + e - v1) - * - * The fourth case (u1 > u0 and v1 <= v0) is not possible - * because it would contradict "b < a" (which is the reason - * why we subtract b from a). - * - * The tricky case is the third one: from the equations, it - * seems that u0 may go out of range. However, the invariants - * and ranges of other values imply that, in that case, the - * new u0 does not actually exceed the range. - * - * We can thus handle the subtraction by adding (r,e) based - * solely on the comparison between v0 and v1. - */ - a = e; - b = r; - u0 = 1; - v0 = 0; - u1 = r; - v1 = e - 1; - hr = (r + 1) >> 1; - he = (e >> 1) + 1; - for (i = 0; i < 62; i ++) { - uint32_t oa, ob, agtb, bgta; - uint32_t sab, sba, da, db; - uint32_t ctl; - - oa = a & 1; /* 1 if a is odd */ - ob = b & 1; /* 1 if b is odd */ - agtb = GT(a, b); /* 1 if a > b */ - bgta = GT(b, a); /* 1 if b > a */ - - sab = oa & ob & agtb; /* 1 if a <- a-b */ - sba = oa & ob & bgta; /* 1 if b <- b-a */ - - /* a <- a-b, u0 <- u0-u1, v0 <- v0-v1 */ - ctl = GT(v1, v0); - a -= b & -sab; - u0 -= (u1 - (r & -ctl)) & -sab; - v0 -= (v1 - (e & -ctl)) & -sab; - - /* b <- b-a, u1 <- u1-u0 mod r, v1 <- v1-v0 mod e */ - ctl = GT(v0, v1); - b -= a & -sba; - u1 -= (u0 - (r & -ctl)) & -sba; - v1 -= (v0 - (e & -ctl)) & -sba; - - da = NOT(oa) | sab; /* 1 if a <- a/2 */ - db = (oa & NOT(ob)) | sba; /* 1 if b <- b/2 */ - - /* a <- a/2, u0 <- u0/2, v0 <- v0/2 */ - ctl = v0 & 1; - a ^= (a ^ (a >> 1)) & -da; - u0 ^= (u0 ^ ((u0 >> 1) + (hr & -ctl))) & -da; - v0 ^= (v0 ^ ((v0 >> 1) + (he & -ctl))) & -da; - - /* b <- b/2, u1 <- u1/2 mod r, v1 <- v1/2 mod e */ - ctl = v1 & 1; - b ^= (b ^ (b >> 1)) & -db; - u1 ^= (u1 ^ ((u1 >> 1) + (hr & -ctl))) & -db; - v1 ^= (v1 ^ ((v1 >> 1) + (he & -ctl))) & -db; - } - - /* - * Check that the GCD is indeed 1. If not, then the key is invalid - * (and there's no harm in leaking that piece of information). - */ - if (a != 1) { - return 0; - } - - /* - * Now we have u0*e - v0*r = 1. Let's compute the result as: - * d = u0 + v0*k - * We still have k in the tmp[] array, and its announced bit - * length is that of phi. - */ - m = k + 1 + len; - m[0] = (1 << 5) + 1; /* bit length is 32 bits, encoded */ - m[1] = v0 & 0x7FFFFFFF; - m[2] = v0 >> 31; - z = m + 3; - br_i31_zero(z, k[0]); - z[1] = u0 & 0x7FFFFFFF; - z[2] = u0 >> 31; - br_i31_mulacc(z, k, m); - - /* - * Encode the result. - */ - br_i31_encode(d, dlen, z); - return dlen; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_pub.c b/src/tls/bearssl/rsa_i31_pub.c deleted file mode 100644 index 5de019938..000000000 --- a/src/tls/bearssl/rsa_i31_pub.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * As a strict minimum, we need four buffers that can hold a - * modular integer. - */ -#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31))) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk) -{ - const unsigned char *n; - size_t nlen; - uint32_t tmp[1 + TLEN]; - uint32_t *m, *a, *t; - size_t fwlen; - long z; - uint32_t m0i, r; - - /* - * Get the actual length of the modulus, and see if it fits within - * our stack buffer. We also check that the length of x[] is valid. - */ - n = pk->n; - nlen = pk->nlen; - while (nlen > 0 && *n == 0) { - n ++; - nlen --; - } - if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { - return 0; - } - z = (long)nlen << 3; - fwlen = 1; - while (z > 0) { - z -= 31; - fwlen ++; - } - /* - * Round up length to an even number. - */ - fwlen += (fwlen & 1); - - /* - * The modulus gets decoded into m[]. - * The value to exponentiate goes into a[]. - * The temporaries for modular exponentiation are in t[]. - */ - m = tmp; - a = m + fwlen; - t = m + 2 * fwlen; - - /* - * Decode the modulus. - */ - br_i31_decode(m, n, nlen); - m0i = br_i31_ninv31(m[1]); - - /* - * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be - * an odd integer. - */ - r = m0i & 1; - - /* - * Decode x[] into a[]; we also check that its value is proper. - */ - r &= br_i31_decode_mod(a, x, xlen, m); - - /* - * Compute the modular exponentiation. - */ - br_i31_modpow_opt(a, pk->e, pk->elen, m, m0i, t, TLEN - 2 * fwlen); - - /* - * Encode the result. - */ - br_i31_encode(x, xlen, a); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i31_pubexp.c b/src/tls/bearssl/rsa_i31_pubexp.c deleted file mode 100644 index 5df1b34e9..000000000 --- a/src/tls/bearssl/rsa_i31_pubexp.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Recompute public exponent, based on factor p and reduced private - * exponent dp. - */ -static uint32_t -get_pubexp(const unsigned char *pbuf, size_t plen, - const unsigned char *dpbuf, size_t dplen) -{ - /* - * dp is the inverse of e modulo p-1. If p = 3 mod 4, then - * p-1 = 2*((p-1)/2). Taken modulo 2, e is odd and has inverse 1; - * thus, dp must be odd. - * - * We compute the inverse of dp modulo (p-1)/2. This requires - * first reducing dp modulo (p-1)/2 (this can be done with a - * conditional subtract, no need to use the generic modular - * reduction function); then, we use moddiv. - */ - - uint32_t tmp[6 * ((BR_MAX_RSA_FACTOR + 61) / 31)]; - uint32_t *p, *dp, *x; - size_t len; - uint32_t e; - - /* - * Compute actual factor length (in bytes) and check that it fits - * under our size constraints. - */ - while (plen > 0 && *pbuf == 0) { - pbuf ++; - plen --; - } - if (plen == 0 || plen < 5 || plen > (BR_MAX_RSA_FACTOR / 8)) { - return 0; - } - - /* - * Compute actual reduced exponent length (in bytes) and check that - * it is not longer than p. - */ - while (dplen > 0 && *dpbuf == 0) { - dpbuf ++; - dplen --; - } - if (dplen > plen || dplen == 0 - || (dplen == plen && dpbuf[0] > pbuf[0])) - { - return 0; - } - - /* - * Verify that p = 3 mod 4 and that dp is odd. - */ - if ((pbuf[plen - 1] & 3) != 3 || (dpbuf[dplen - 1] & 1) != 1) { - return 0; - } - - /* - * Decode p and compute (p-1)/2. - */ - p = tmp; - br_i31_decode(p, pbuf, plen); - len = (p[0] + 63) >> 5; - br_i31_rshift(p, 1); - - /* - * Decode dp and make sure its announced bit length matches that of - * p (we already know that the size of dp, in bits, does not exceed - * the size of p, so we just have to copy the header word). - */ - dp = p + len; - memset(dp, 0, len * sizeof *dp); - br_i31_decode(dp, dpbuf, dplen); - dp[0] = p[0]; - - /* - * Subtract (p-1)/2 from dp if necessary. - */ - br_i31_sub(dp, p, NOT(br_i31_sub(dp, p, 0))); - - /* - * If another subtraction is needed, then this means that the - * value was invalid. We don't care to leak information about - * invalid keys. - */ - if (br_i31_sub(dp, p, 0) == 0) { - return 0; - } - - /* - * Invert dp modulo (p-1)/2. If the inversion fails, then the - * key value was invalid. - */ - x = dp + len; - br_i31_zero(x, p[0]); - x[1] = 1; - if (br_i31_moddiv(x, dp, p, br_i31_ninv31(p[1]), x + len) == 0) { - return 0; - } - - /* - * We now have an inverse. We must set it to zero (error) if its - * length is greater than 32 bits and/or if it is an even integer. - * Take care that the bit_length function returns an encoded - * bit length. - */ - e = (uint32_t)x[1] | ((uint32_t)x[2] << 31); - e &= -LT(br_i31_bit_length(x + 1, len - 1), 34); - e &= -(e & 1); - return e; -} - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk) -{ - /* - * Get the public exponent from both p and q. This is the right - * exponent if we get twice the same value. - */ - uint32_t ep, eq; - - ep = get_pubexp(sk->p, sk->plen, sk->dp, sk->dplen); - eq = get_pubexp(sk->q, sk->qlen, sk->dq, sk->dqlen); - return ep & -EQ(ep, eq); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_oaep_decrypt.c b/src/tls/bearssl/rsa_i32_oaep_decrypt.c deleted file mode 100644 index f6575dcf7..000000000 --- a/src/tls/bearssl/rsa_i32_oaep_decrypt.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i32_oaep_decrypt(const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len) -{ - uint32_t r; - - if (*len != ((sk->n_bitlen + 7) >> 3)) { - return 0; - } - r = br_rsa_i32_private(data, sk); - r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_oaep_encrypt.c b/src/tls/bearssl/rsa_i32_oaep_encrypt.c deleted file mode 100644 index dcedb3a80..000000000 --- a/src/tls/bearssl/rsa_i32_oaep_encrypt.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -size_t -br_rsa_i32_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len) -{ - size_t dlen; - - dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, - pk, dst, dst_max_len, src, src_len); - if (dlen == 0) { - return 0; - } - return dlen & -(size_t)br_rsa_i32_public(dst, dlen, pk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_pkcs1_sign.c b/src/tls/bearssl/rsa_i32_pkcs1_sign.c deleted file mode 100644 index 6655aa34c..000000000 --- a/src/tls/bearssl/rsa_i32_pkcs1_sign.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x) -{ - if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { - return 0; - } - return br_rsa_i32_private(x, sk); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_pkcs1_vrfy.c b/src/tls/bearssl/rsa_i32_pkcs1_vrfy.c deleted file mode 100644 index eeecc97e3..000000000 --- a/src/tls/bearssl/rsa_i32_pkcs1_vrfy.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out) -{ - unsigned char sig[BR_MAX_RSA_SIZE >> 3]; - - if (xlen > (sizeof sig)) { - return 0; - } - memcpy(sig, x, xlen); - if (!br_rsa_i32_public(sig, xlen, pk)) { - return 0; - } - return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_priv.c b/src/tls/bearssl/rsa_i32_priv.c deleted file mode 100644 index 5ed1537a1..000000000 --- a/src/tls/bearssl/rsa_i32_priv.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define U (1 + (BR_MAX_RSA_FACTOR >> 5)) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i32_private(unsigned char *x, const br_rsa_private_key *sk) -{ - const unsigned char *p, *q; - size_t plen, qlen; - uint32_t tmp[6 * U]; - uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; - uint32_t p0i, q0i; - size_t xlen, u; - uint32_t r; - - /* - * All our temporary buffers are from the tmp[] array. - * - * The mp, mq, s1, s2, t1 and t2 buffers are large enough to - * contain a RSA factor. The t3 buffer can contain a complete - * RSA modulus. t3 shares its storage space with s2, s1 and t1, - * in that order (this is important, see below). - */ - mq = tmp; - mp = tmp + U; - t2 = tmp + 2 * U; - s2 = tmp + 3 * U; - s1 = tmp + 4 * U; - t1 = tmp + 5 * U; - t3 = s2; - - /* - * Compute the actual lengths (in bytes) of p and q, and check - * that they fit within our stack buffers. - */ - p = sk->p; - plen = sk->plen; - while (plen > 0 && *p == 0) { - p ++; - plen --; - } - q = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *q == 0) { - q ++; - qlen --; - } - if (plen > (BR_MAX_RSA_FACTOR >> 3) - || qlen > (BR_MAX_RSA_FACTOR >> 3)) - { - return 0; - } - - /* - * Decode p and q. - */ - br_i32_decode(mp, p, plen); - br_i32_decode(mq, q, qlen); - - /* - * Recompute modulus, to compare with the source value. - */ - br_i32_zero(t2, mp[0]); - br_i32_mulacc(t2, mp, mq); - xlen = (sk->n_bitlen + 7) >> 3; - br_i32_encode(t2 + 2 * U, xlen, t2); - u = xlen; - r = 0; - while (u > 0) { - uint32_t wn, wx; - - u --; - wn = ((unsigned char *)(t2 + 2 * U))[u]; - wx = x[u]; - r = ((wx - (wn + r)) >> 8) & 1; - } - - /* - * Compute s1 = x^dp mod p. - */ - p0i = br_i32_ninv32(mp[1]); - br_i32_decode_reduce(s1, x, xlen, mp); - br_i32_modpow(s1, sk->dp, sk->dplen, mp, p0i, t1, t2); - - /* - * Compute s2 = x^dq mod q. - */ - q0i = br_i32_ninv32(mq[1]); - br_i32_decode_reduce(s2, x, xlen, mq); - br_i32_modpow(s2, sk->dq, sk->dqlen, mq, q0i, t1, t2); - - /* - * Compute: - * h = (s1 - s2)*(1/q) mod p - * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is - * unclear about whether p may be lower than q (some existing, - * widely deployed implementations of RSA don't tolerate p < q), - * but we want to support that occurrence, so we need to use the - * reduction function. - * - * Since we use br_i32_decode_reduce() for iq (purportedly, the - * inverse of q modulo p), we also tolerate improperly large - * values for this parameter. - */ - br_i32_reduce(t2, s2, mp); - br_i32_add(s1, mp, br_i32_sub(s1, t2, 1)); - br_i32_to_monty(s1, mp); - br_i32_decode_reduce(t1, sk->iq, sk->iqlen, mp); - br_i32_montymul(t2, s1, t1, mp, p0i); - - /* - * h is now in t2. We compute the final result: - * s = s2 + q*h - * All these operations are non-modular. - * - * We need mq, s2 and t2. We use the t3 buffer as destination. - * The buffers mp, s1 and t1 are no longer needed. Moreover, - * the first step is to copy s2 into the destination buffer t3. - * We thus arranged for t3 to actually share space with s2, and - * to be followed by the space formerly used by s1 and t1. - */ - br_i32_mulacc(t3, mq, t2); - - /* - * Encode the result. Since we already checked the value of xlen, - * we can just use it right away. - */ - br_i32_encode(x, xlen, t3); - - /* - * The only error conditions remaining at that point are invalid - * values for p and q (even integers). - */ - return p0i & q0i & r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i32_pub.c b/src/tls/bearssl/rsa_i32_pub.c deleted file mode 100644 index 2101b2e04..000000000 --- a/src/tls/bearssl/rsa_i32_pub.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i32_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk) -{ - const unsigned char *n; - size_t nlen; - uint32_t m[1 + (BR_MAX_RSA_SIZE >> 5)]; - uint32_t a[1 + (BR_MAX_RSA_SIZE >> 5)]; - uint32_t t1[1 + (BR_MAX_RSA_SIZE >> 5)]; - uint32_t t2[1 + (BR_MAX_RSA_SIZE >> 5)]; - uint32_t m0i, r; - - /* - * Get the actual length of the modulus, and see if it fits within - * our stack buffer. We also check that the length of x[] is valid. - */ - n = pk->n; - nlen = pk->nlen; - while (nlen > 0 && *n == 0) { - n ++; - nlen --; - } - if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { - return 0; - } - br_i32_decode(m, n, nlen); - m0i = br_i32_ninv32(m[1]); - - /* - * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be - * an odd integer. - */ - r = m0i & 1; - - /* - * Decode x[] into a[]; we also check that its value is proper. - */ - r &= br_i32_decode_mod(a, x, xlen, m); - - /* - * Compute the modular exponentiation. - */ - br_i32_modpow(a, pk->e, pk->elen, m, m0i, t1, t2); - - /* - * Encode the result. - */ - br_i32_encode(x, xlen, a); - return r; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_keygen.c b/src/tls/bearssl/rsa_i62_keygen.c deleted file mode 100644 index 72adab443..000000000 --- a/src/tls/bearssl/rsa_i62_keygen.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_keygen(const br_prng_class **rng, - br_rsa_private_key *sk, void *kbuf_priv, - br_rsa_public_key *pk, void *kbuf_pub, - unsigned size, uint32_t pubexp) -{ - return br_rsa_i31_keygen_inner(rng, - sk, kbuf_priv, pk, kbuf_pub, size, pubexp, - &br_i62_modpow_opt_as_i31); -} - -/* see bearssl_rsa.h */ -br_rsa_keygen -br_rsa_i62_keygen_get() -{ - return &br_rsa_i62_keygen; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_keygen -br_rsa_i62_keygen_get() -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_oaep_decrypt.c b/src/tls/bearssl/rsa_i62_oaep_decrypt.c deleted file mode 100644 index 8dcee5c7c..000000000 --- a/src/tls/bearssl/rsa_i62_oaep_decrypt.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_oaep_decrypt(const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_private_key *sk, void *data, size_t *len) -{ - uint32_t r; - - if (*len != ((sk->n_bitlen + 7) >> 3)) { - return 0; - } - r = br_rsa_i62_private(data, sk); - r &= br_rsa_oaep_unpad(dig, label, label_len, data, len); - return r; -} - -/* see bearssl_rsa.h */ -br_rsa_oaep_decrypt -br_rsa_i62_oaep_decrypt_get(void) -{ - return &br_rsa_i62_oaep_decrypt; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_oaep_decrypt -br_rsa_i62_oaep_decrypt_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_oaep_encrypt.c b/src/tls/bearssl/rsa_i62_oaep_encrypt.c deleted file mode 100644 index ecf873e3f..000000000 --- a/src/tls/bearssl/rsa_i62_oaep_encrypt.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* see bearssl_rsa.h */ -size_t -br_rsa_i62_oaep_encrypt( - const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len) -{ - size_t dlen; - - dlen = br_rsa_oaep_pad(rnd, dig, label, label_len, - pk, dst, dst_max_len, src, src_len); - if (dlen == 0) { - return 0; - } - return dlen & -(size_t)br_rsa_i62_public(dst, dlen, pk); -} - -/* see bearssl_rsa.h */ -br_rsa_oaep_encrypt -br_rsa_i62_oaep_encrypt_get(void) -{ - return &br_rsa_i62_oaep_encrypt; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_oaep_encrypt -br_rsa_i62_oaep_encrypt_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_pkcs1_sign.c b/src/tls/bearssl/rsa_i62_pkcs1_sign.c deleted file mode 100644 index df31d406a..000000000 --- a/src/tls/bearssl/rsa_i62_pkcs1_sign.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - const br_rsa_private_key *sk, unsigned char *x) -{ - if (!br_rsa_pkcs1_sig_pad(hash_oid, hash, hash_len, sk->n_bitlen, x)) { - return 0; - } - return br_rsa_i62_private(x, sk); -} - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_sign -br_rsa_i62_pkcs1_sign_get(void) -{ - return &br_rsa_i62_pkcs1_sign; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_sign -br_rsa_i62_pkcs1_sign_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_pkcs1_vrfy.c b/src/tls/bearssl/rsa_i62_pkcs1_vrfy.c deleted file mode 100644 index a9cc3125e..000000000 --- a/src/tls/bearssl/rsa_i62_pkcs1_vrfy.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen, - const unsigned char *hash_oid, size_t hash_len, - const br_rsa_public_key *pk, unsigned char *hash_out) -{ - unsigned char sig[BR_MAX_RSA_SIZE >> 3]; - - if (xlen > (sizeof sig)) { - return 0; - } - memcpy(sig, x, xlen); - if (!br_rsa_i62_public(sig, xlen, pk)) { - return 0; - } - return br_rsa_pkcs1_sig_unpad(sig, xlen, hash_oid, hash_len, hash_out); -} - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_vrfy -br_rsa_i62_pkcs1_vrfy_get(void) -{ - return &br_rsa_i62_pkcs1_vrfy; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_pkcs1_vrfy -br_rsa_i62_pkcs1_vrfy_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_priv.c b/src/tls/bearssl/rsa_i62_priv.c deleted file mode 100644 index 4f21d6732..000000000 --- a/src/tls/bearssl/rsa_i62_priv.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -#define U (2 + ((BR_MAX_RSA_FACTOR + 30) / 31)) -#define TLEN (4 * U) /* TLEN is counted in 64-bit words */ - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_private(unsigned char *x, const br_rsa_private_key *sk) -{ - const unsigned char *p, *q; - size_t plen, qlen; - size_t fwlen; - uint32_t p0i, q0i; - size_t xlen, u; - uint64_t tmp[TLEN]; - long z; - uint32_t *mp, *mq, *s1, *s2, *t1, *t2, *t3; - uint32_t r; - - /* - * Compute the actual lengths of p and q, in bytes. - * These lengths are not considered secret (we cannot really hide - * them anyway in constant-time code). - */ - p = sk->p; - plen = sk->plen; - while (plen > 0 && *p == 0) { - p ++; - plen --; - } - q = sk->q; - qlen = sk->qlen; - while (qlen > 0 && *q == 0) { - q ++; - qlen --; - } - - /* - * Compute the maximum factor length, in words. - */ - z = (long)(plen > qlen ? plen : qlen) << 3; - fwlen = 1; - while (z > 0) { - z -= 31; - fwlen ++; - } - - /* - * Convert size to 62-bit words. - */ - fwlen = (fwlen + 1) >> 1; - - /* - * We need to fit at least 6 values in the stack buffer. - */ - if (6 * fwlen > TLEN) { - return 0; - } - - /* - * Compute signature length (in bytes). - */ - xlen = (sk->n_bitlen + 7) >> 3; - - /* - * Decode q. - */ - mq = (uint32_t *)tmp; - br_i31_decode(mq, q, qlen); - - /* - * Decode p. - */ - t1 = (uint32_t *)(tmp + fwlen); - br_i31_decode(t1, p, plen); - - /* - * Compute the modulus (product of the two factors), to compare - * it with the source value. We use br_i31_mulacc(), since it's - * already used later on. - */ - t2 = (uint32_t *)(tmp + 2 * fwlen); - br_i31_zero(t2, mq[0]); - br_i31_mulacc(t2, mq, t1); - - /* - * We encode the modulus into bytes, to perform the comparison - * with bytes. We know that the product length, in bytes, is - * exactly xlen. - * The comparison actually computes the carry when subtracting - * the modulus from the source value; that carry must be 1 for - * a value in the correct range. We keep it in r, which is our - * accumulator for the error code. - */ - t3 = (uint32_t *)(tmp + 4 * fwlen); - br_i31_encode(t3, xlen, t2); - u = xlen; - r = 0; - while (u > 0) { - uint32_t wn, wx; - - u --; - wn = ((unsigned char *)t3)[u]; - wx = x[u]; - r = ((wx - (wn + r)) >> 8) & 1; - } - - /* - * Move the decoded p to another temporary buffer. - */ - mp = (uint32_t *)(tmp + 2 * fwlen); - memmove(mp, t1, 2 * fwlen * sizeof *t1); - - /* - * Compute s2 = x^dq mod q. - */ - q0i = br_i31_ninv31(mq[1]); - s2 = (uint32_t *)(tmp + fwlen); - br_i31_decode_reduce(s2, x, xlen, mq); - r &= br_i62_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i, - tmp + 3 * fwlen, TLEN - 3 * fwlen); - - /* - * Compute s1 = x^dp mod p. - */ - p0i = br_i31_ninv31(mp[1]); - s1 = (uint32_t *)(tmp + 3 * fwlen); - br_i31_decode_reduce(s1, x, xlen, mp); - r &= br_i62_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i, - tmp + 4 * fwlen, TLEN - 4 * fwlen); - - /* - * Compute: - * h = (s1 - s2)*(1/q) mod p - * s1 is an integer modulo p, but s2 is modulo q. PKCS#1 is - * unclear about whether p may be lower than q (some existing, - * widely deployed implementations of RSA don't tolerate p < q), - * but we want to support that occurrence, so we need to use the - * reduction function. - * - * Since we use br_i31_decode_reduce() for iq (purportedly, the - * inverse of q modulo p), we also tolerate improperly large - * values for this parameter. - */ - t1 = (uint32_t *)(tmp + 4 * fwlen); - t2 = (uint32_t *)(tmp + 5 * fwlen); - br_i31_reduce(t2, s2, mp); - br_i31_add(s1, mp, br_i31_sub(s1, t2, 1)); - br_i31_to_monty(s1, mp); - br_i31_decode_reduce(t1, sk->iq, sk->iqlen, mp); - br_i31_montymul(t2, s1, t1, mp, p0i); - - /* - * h is now in t2. We compute the final result: - * s = s2 + q*h - * All these operations are non-modular. - * - * We need mq, s2 and t2. We use the t3 buffer as destination. - * The buffers mp, s1 and t1 are no longer needed, so we can - * reuse them for t3. Moreover, the first step of the computation - * is to copy s2 into t3, after which s2 is not needed. Right - * now, mq is in slot 0, s2 is in slot 1, and t2 is in slot 5. - * Therefore, we have ample room for t3 by simply using s2. - */ - t3 = s2; - br_i31_mulacc(t3, mq, t2); - - /* - * Encode the result. Since we already checked the value of xlen, - * we can just use it right away. - */ - br_i31_encode(x, xlen, t3); - - /* - * The only error conditions remaining at that point are invalid - * values for p and q (even integers). - */ - return p0i & q0i & r; -} - -/* see bearssl_rsa.h */ -br_rsa_private -br_rsa_i62_private_get(void) -{ - return &br_rsa_i62_private; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_private -br_rsa_i62_private_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_i62_pub.c b/src/tls/bearssl/rsa_i62_pub.c deleted file mode 100644 index 69644640d..000000000 --- a/src/tls/bearssl/rsa_i62_pub.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if BR_INT128 || BR_UMUL128 - -/* - * As a strict minimum, we need four buffers that can hold a - * modular integer. But TLEN is expressed in 64-bit words. - */ -#define TLEN (2 * (2 + ((BR_MAX_RSA_SIZE + 30) / 31))) - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_i62_public(unsigned char *x, size_t xlen, - const br_rsa_public_key *pk) -{ - const unsigned char *n; - size_t nlen; - uint64_t tmp[TLEN]; - uint32_t *m, *a; - size_t fwlen; - long z; - uint32_t m0i, r; - - /* - * Get the actual length of the modulus, and see if it fits within - * our stack buffer. We also check that the length of x[] is valid. - */ - n = pk->n; - nlen = pk->nlen; - while (nlen > 0 && *n == 0) { - n ++; - nlen --; - } - if (nlen == 0 || nlen > (BR_MAX_RSA_SIZE >> 3) || xlen != nlen) { - return 0; - } - z = (long)nlen << 3; - fwlen = 1; - while (z > 0) { - z -= 31; - fwlen ++; - } - /* - * Convert fwlen to a count in 62-bit words. - */ - fwlen = (fwlen + 1) >> 1; - - /* - * The modulus gets decoded into m[]. - * The value to exponentiate goes into a[]. - */ - m = (uint32_t *)tmp; - a = (uint32_t *)(tmp + fwlen); - - /* - * Decode the modulus. - */ - br_i31_decode(m, n, nlen); - m0i = br_i31_ninv31(m[1]); - - /* - * Note: if m[] is even, then m0i == 0. Otherwise, m0i must be - * an odd integer. - */ - r = m0i & 1; - - /* - * Decode x[] into a[]; we also check that its value is proper. - */ - r &= br_i31_decode_mod(a, x, xlen, m); - - /* - * Compute the modular exponentiation. - */ - br_i62_modpow_opt(a, pk->e, pk->elen, m, m0i, - tmp + 2 * fwlen, TLEN - 2 * fwlen); - - /* - * Encode the result. - */ - br_i31_encode(x, xlen, a); - return r; -} - -/* see bearssl_rsa.h */ -br_rsa_public -br_rsa_i62_public_get(void) -{ - return &br_rsa_i62_public; -} - -#else - -/* see bearssl_rsa.h */ -br_rsa_public -br_rsa_i62_public_get(void) -{ - return 0; -} - -#endif - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_oaep_pad.c b/src/tls/bearssl/rsa_oaep_pad.c deleted file mode 100644 index fe6daaff0..000000000 --- a/src/tls/bearssl/rsa_oaep_pad.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Hash some data. This is put as a separate function so that stack - * allocation of the hash function context is done only for the duration - * of the hash. - */ -static void -hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len) -{ - br_hash_compat_context hc; - - hc.vtable = dig; - dig->init(&hc.vtable); - dig->update(&hc.vtable, src, len); - dig->out(&hc.vtable, dst); -} - -/* see inner.h */ -size_t -br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig, - const void *label, size_t label_len, - const br_rsa_public_key *pk, - void *dst, size_t dst_max_len, - const void *src, size_t src_len) -{ - size_t k, hlen; - unsigned char *buf; - - hlen = br_digest_size(dig); - - /* - * Compute actual modulus length (in bytes). - */ - k = pk->nlen; - while (k > 0 && pk->n[k - 1] == 0) { - k --; - } - - /* - * An error is reported if: - * - the modulus is too short; - * - the source message length is too long; - * - the destination buffer is too short. - */ - if (k < ((hlen << 1) + 2) - || src_len > (k - (hlen << 1) - 2) - || dst_max_len < k) - { - return 0; - } - - /* - * Apply padding. At this point, things cannot fail. - */ - buf = dst; - - /* - * Assemble: DB = lHash || PS || 0x01 || M - * We first place the source message M with memmove(), so that - * overlaps between source and destination buffers are supported. - */ - memmove(buf + k - src_len, src, src_len); - hash_data(dig, buf + 1 + hlen, label, label_len); - memset(buf + 1 + (hlen << 1), 0, k - src_len - (hlen << 1) - 2); - buf[k - src_len - 1] = 0x01; - - /* - * Make the random seed. - */ - (*rnd)->generate(rnd, buf + 1, hlen); - - /* - * Mask DB with the mask generated from the seed. - */ - br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen); - - /* - * Mask the seed with the mask generated from the masked DB. - */ - br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1); - - /* - * Padding result: EM = 0x00 || maskedSeed || maskedDB. - */ - buf[0] = 0x00; - return k; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_oaep_unpad.c b/src/tls/bearssl/rsa_oaep_unpad.c deleted file mode 100644 index adec410d4..000000000 --- a/src/tls/bearssl/rsa_oaep_unpad.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Hash some data and XOR the result into the provided buffer. This is put - * as a separate function so that stack allocation of the hash function - * context is done only for the duration of the hash. - */ -static void -xor_hash_data(const br_hash_class *dig, void *dst, const void *src, size_t len) -{ - br_hash_compat_context hc; - unsigned char tmp[64]; - unsigned char *buf; - size_t u, hlen; - - hc.vtable = dig; - dig->init(&hc.vtable); - dig->update(&hc.vtable, src, len); - dig->out(&hc.vtable, tmp); - buf = dst; - hlen = br_digest_size(dig); - for (u = 0; u < hlen; u ++) { - buf[u] ^= tmp[u]; - } -} - -/* see inner.h */ -uint32_t -br_rsa_oaep_unpad(const br_hash_class *dig, - const void *label, size_t label_len, - void *data, size_t *len) -{ - size_t u, k, hlen; - unsigned char *buf; - uint32_t r, s, zlen; - - hlen = br_digest_size(dig); - k = *len; - buf = data; - - /* - * There must be room for the padding. - */ - if (k < ((hlen << 1) + 2)) { - return 0; - } - - /* - * Unmask the seed, then the DB value. - */ - br_mgf1_xor(buf + 1, hlen, dig, buf + 1 + hlen, k - hlen - 1); - br_mgf1_xor(buf + 1 + hlen, k - hlen - 1, dig, buf + 1, hlen); - - /* - * Hash the label and XOR it with the value in the array; if - * they are equal then these should yield only zeros. - */ - xor_hash_data(dig, buf + 1 + hlen, label, label_len); - - /* - * At that point, if the padding was correct, when we should - * have: 0x00 || seed || 0x00 ... 0x00 0x01 || M - * Padding is valid as long as: - * - There is at least hlen+1 leading bytes of value 0x00. - * - There is at least one non-zero byte. - * - The first (leftmost) non-zero byte has value 0x01. - * - * Ultimately, we may leak the resulting message length, i.e. - * the position of the byte of value 0x01, but we must take care - * to do so only if the number of zero bytes has been verified - * to be at least hlen+1. - * - * The loop below counts the number of bytes of value 0x00, and - * checks that the next byte has value 0x01, in constant-time. - * - * - If the initial byte (before the seed) is not 0x00, then - * r and s are set to 0, and stay there. - * - Value r is 1 until the first non-zero byte is reached - * (after the seed); it switches to 0 at that point. - * - Value s is set to 1 if and only if the data encountered - * at the time of the transition of r from 1 to 0 has value - * exactly 0x01. - * - Value zlen counts the number of leading bytes of value zero - * (after the seed). - */ - r = 1 - ((buf[0] + 0xFF) >> 8); - s = 0; - zlen = 0; - for (u = hlen + 1; u < k; u ++) { - uint32_t w, nz; - - w = buf[u]; - - /* - * nz == 1 only for the first non-zero byte. - */ - nz = r & ((w + 0xFF) >> 8); - s |= nz & EQ(w, 0x01); - r &= NOT(nz); - zlen += r; - } - - /* - * Padding is correct only if s == 1, _and_ zlen >= hlen. - */ - s &= GE(zlen, (uint32_t)hlen); - - /* - * At that point, padding was verified, and we are now allowed - * to make conditional jumps. - */ - if (s) { - size_t plen; - - plen = 2 + hlen + zlen; - k -= plen; - memmove(buf, buf + plen, k); - *len = k; - } - return s; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_pkcs1_sig_pad.c b/src/tls/bearssl/rsa_pkcs1_sig_pad.c deleted file mode 100644 index 7fc4a5e2a..000000000 --- a/src/tls/bearssl/rsa_pkcs1_sig_pad.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -uint32_t -br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid, - const unsigned char *hash, size_t hash_len, - uint32_t n_bitlen, unsigned char *x) -{ - size_t u, x3, xlen; - - /* - * Padded hash value has format: - * 00 01 FF .. FF 00 30 x1 30 x2 06 x3 OID 05 00 04 x4 HASH - * - * with the following rules: - * - * -- Total length is equal to the modulus length (unsigned - * encoding). - * - * -- There must be at least eight bytes of value 0xFF. - * - * -- x4 is equal to the hash length (hash_len). - * - * -- x3 is equal to the encoded OID value length (hash_oid[0]). - * - * -- x2 = x3 + 4. - * - * -- x1 = x2 + x4 + 4 = x3 + x4 + 8. - * - * Note: the "05 00" is optional (signatures with and without - * that sequence exist in practice), but notes in PKCS#1 seem to - * indicate that the presence of that sequence (specifically, - * an ASN.1 NULL value for the hash parameters) may be slightly - * more "standard" than the opposite. - */ - xlen = (n_bitlen + 7) >> 3; - - if (hash_oid == NULL) { - if (xlen < hash_len + 11) { - return 0; - } - x[0] = 0x00; - x[1] = 0x01; - u = xlen - hash_len; - memset(x + 2, 0xFF, u - 3); - x[u - 1] = 0x00; - } else { - x3 = hash_oid[0]; - - /* - * Check that there is enough room for all the elements, - * including at least eight bytes of value 0xFF. - */ - if (xlen < (x3 + hash_len + 21)) { - return 0; - } - x[0] = 0x00; - x[1] = 0x01; - u = xlen - x3 - hash_len - 11; - memset(x + 2, 0xFF, u - 2); - x[u] = 0x00; - x[u + 1] = 0x30; - x[u + 2] = x3 + hash_len + 8; - x[u + 3] = 0x30; - x[u + 4] = x3 + 4; - x[u + 5] = 0x06; - memcpy(x + u + 6, hash_oid, x3 + 1); - u += x3 + 7; - x[u ++] = 0x05; - x[u ++] = 0x00; - x[u ++] = 0x04; - x[u ++] = hash_len; - } - memcpy(x + u, hash, hash_len); - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_pkcs1_sig_unpad.c b/src/tls/bearssl/rsa_pkcs1_sig_unpad.c deleted file mode 100644 index 2ab198203..000000000 --- a/src/tls/bearssl/rsa_pkcs1_sig_unpad.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, - const unsigned char *hash_oid, size_t hash_len, - unsigned char *hash_out) -{ - static const unsigned char pad1[] = { - 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF - }; - - unsigned char pad2[43]; - size_t u, x2, x3, pad_len, zlen; - - if (sig_len < 11) { - return 0; - } - - /* - * Expected format: - * 00 01 FF ... FF 00 30 x1 30 x2 06 x3 OID [ 05 00 ] 04 x4 HASH - * - * with the following rules: - * - * -- Total length is that of the modulus and the signature - * (this was already verified by br_rsa_i31_public()). - * - * -- There are at least eight bytes of value 0xFF. - * - * -- x4 is equal to the hash length (hash_len). - * - * -- x3 is equal to the encoded OID value length (so x3 is the - * first byte of hash_oid[]). - * - * -- If the "05 00" is present, then x2 == x3 + 4; otherwise, - * x2 == x3 + 2. - * - * -- x1 == x2 + x4 + 4. - * - * So the total length after the last "FF" is either x3 + x4 + 11 - * (with the "05 00") or x3 + x4 + 9 (without the "05 00"). - */ - - /* - * Check the "00 01 FF .. FF 00" with at least eight 0xFF bytes. - * The comparison is valid because we made sure that the signature - * is at least 11 bytes long. - */ - if (memcmp(sig, pad1, sizeof pad1) != 0) { - return 0; - } - for (u = sizeof pad1; u < sig_len; u ++) { - if (sig[u] != 0xFF) { - break; - } - } - - /* - * Remaining length is sig_len - u bytes (including the 00 just - * after the last FF). This must be equal to one of the two - * possible values (depending on whether the "05 00" sequence is - * present or not). - */ - if (hash_oid == NULL) { - if (sig_len - u != hash_len + 1 || sig[u] != 0x00) { - return 0; - } - } else { - x3 = hash_oid[0]; - pad_len = x3 + 9; - memset(pad2, 0, pad_len); - zlen = sig_len - u - hash_len; - if (zlen == pad_len) { - x2 = x3 + 2; - } else if (zlen == pad_len + 2) { - x2 = x3 + 4; - pad_len = zlen; - pad2[pad_len - 4] = 0x05; - } else { - return 0; - } - pad2[1] = 0x30; - pad2[2] = x2 + hash_len + 4; - pad2[3] = 0x30; - pad2[4] = x2; - pad2[5] = 0x06; - memcpy(pad2 + 6, hash_oid, x3 + 1); - pad2[pad_len - 2] = 0x04; - pad2[pad_len - 1] = hash_len; - if (memcmp(pad2, sig + u, pad_len) != 0) { - return 0; - } - } - memcpy(hash_out, sig + sig_len - hash_len, hash_len); - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/rsa_ssl_decrypt.c b/src/tls/bearssl/rsa_ssl_decrypt.c deleted file mode 100644 index 6464c328d..000000000 --- a/src/tls/bearssl/rsa_ssl_decrypt.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_rsa.h */ -uint32_t -br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk, - unsigned char *data, size_t len) -{ - uint32_t x; - size_t u; - - /* - * A first check on length. Since this test works only on the - * buffer length, it needs not (and cannot) be constant-time. - */ - if (len < 59 || len != (sk->n_bitlen + 7) >> 3) { - return 0; - } - x = core(data, sk); - - x &= EQ(data[0], 0x00); - x &= EQ(data[1], 0x02); - for (u = 2; u < (len - 49); u ++) { - x &= NEQ(data[u], 0); - } - x &= EQ(data[len - 49], 0x00); - memmove(data, data + len - 48, 48); - return x; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/settings.c b/src/tls/bearssl/settings.c deleted file mode 100644 index 509003f92..000000000 --- a/src/tls/bearssl/settings.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static const br_config_option config[] = { - { "BR_64", -#if BR_64 - 1 -#else - 0 -#endif - }, - { "BR_AES_X86NI", -#if BR_AES_X86NI - 1 -#else - 0 -#endif - }, - { "BR_amd64", -#if BR_amd64 - 1 -#else - 0 -#endif - }, - { "BR_ARMEL_CORTEXM_GCC", -#if BR_ARMEL_CORTEXM_GCC - 1 -#else - 0 -#endif - }, - { "BR_BE_UNALIGNED", -#if BR_BE_UNALIGNED - 1 -#else - 0 -#endif - }, - { "BR_CLANG", -#if BR_CLANG - 1 -#else - 0 -#endif - }, - { "BR_CLANG_3_7", -#if BR_CLANG_3_7 - 1 -#else - 0 -#endif - }, - { "BR_CLANG_3_8", -#if BR_CLANG_3_8 - 1 -#else - 0 -#endif - }, - { "BR_CT_MUL15", -#if BR_CT_MUL15 - 1 -#else - 0 -#endif - }, - { "BR_CT_MUL31", -#if BR_CT_MUL31 - 1 -#else - 0 -#endif - }, - { "BR_GCC", -#if BR_GCC - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_4", -#if BR_GCC_4_4 - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_5", -#if BR_GCC_4_5 - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_6", -#if BR_GCC_4_6 - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_7", -#if BR_GCC_4_7 - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_8", -#if BR_GCC_4_8 - 1 -#else - 0 -#endif - }, - { "BR_GCC_4_9", -#if BR_GCC_4_9 - 1 -#else - 0 -#endif - }, - { "BR_GCC_5_0", -#if BR_GCC_5_0 - 1 -#else - 0 -#endif - }, - { "BR_i386", -#if BR_i386 - 1 -#else - 0 -#endif - }, - { "BR_INT128", -#if BR_INT128 - 1 -#else - 0 -#endif - }, - { "BR_LE_UNALIGNED", -#if BR_LE_UNALIGNED - 1 -#else - 0 -#endif - }, - { "BR_LOMUL", -#if BR_LOMUL - 1 -#else - 0 -#endif - }, - { "BR_MAX_EC_SIZE", BR_MAX_EC_SIZE }, - { "BR_MAX_RSA_SIZE", BR_MAX_RSA_SIZE }, - { "BR_MAX_RSA_FACTOR", BR_MAX_RSA_FACTOR }, - { "BR_MSC", -#if BR_MSC - 1 -#else - 0 -#endif - }, - { "BR_MSC_2005", -#if BR_MSC_2005 - 1 -#else - 0 -#endif - }, - { "BR_MSC_2008", -#if BR_MSC_2008 - 1 -#else - 0 -#endif - }, - { "BR_MSC_2010", -#if BR_MSC_2010 - 1 -#else - 0 -#endif - }, - { "BR_MSC_2012", -#if BR_MSC_2012 - 1 -#else - 0 -#endif - }, - { "BR_MSC_2013", -#if BR_MSC_2013 - 1 -#else - 0 -#endif - }, - { "BR_MSC_2015", -#if BR_MSC_2015 - 1 -#else - 0 -#endif - }, - { "BR_POWER8", -#if BR_POWER8 - 1 -#else - 0 -#endif - }, - { "BR_RDRAND", -#if BR_RDRAND - 1 -#else - 0 -#endif - }, - { "BR_SLOW_MUL", -#if BR_SLOW_MUL - 1 -#else - 0 -#endif - }, - { "BR_SLOW_MUL15", -#if BR_SLOW_MUL15 - 1 -#else - 0 -#endif - }, - { "BR_SSE2", -#if BR_SSE2 - 1 -#else - 0 -#endif - }, - { "BR_UMUL128", -#if BR_UMUL128 - 1 -#else - 0 -#endif - }, - { "BR_USE_UNIX_TIME", -#if BR_USE_UNIX_TIME - 1 -#else - 0 -#endif - }, - { "BR_USE_WIN32_RAND", -#if BR_USE_WIN32_RAND - 1 -#else - 0 -#endif - }, - { "BR_USE_WIN32_TIME", -#if BR_USE_WIN32_TIME - 1 -#else - 0 -#endif - }, - - { NULL, 0 } -}; - -/* see bearssl.h */ -const br_config_option * -br_get_config(void) -{ - return config; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/sha1.c b/src/tls/bearssl/sha1.c deleted file mode 100644 index 935e63b82..000000000 --- a/src/tls/bearssl/sha1.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) -#define G(B, C, D) ((B) ^ (C) ^ (D)) -#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B))) -#define I(B, C, D) G(B, C, D) - -#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - -#define K1 ((uint32_t)0x5A827999) -#define K2 ((uint32_t)0x6ED9EBA1) -#define K3 ((uint32_t)0x8F1BBCDC) -#define K4 ((uint32_t)0xCA62C1D6) - -/* see inner.h */ -const uint32_t br_sha1_IV[5] = { - 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 -}; - -/* see inner.h */ -void -br_sha1_round(const unsigned char *buf, uint32_t *val) -{ - uint32_t m[80]; - uint32_t a, b, c, d, e; - int i; - - a = val[0]; - b = val[1]; - c = val[2]; - d = val[3]; - e = val[4]; - br_range_dec32be(m, 16, buf); - for (i = 16; i < 80; i ++) { - uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]; - m[i] = ROTL(x, 1); - } - - for (i = 0; i < 20; i += 5) { - e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 20; i < 40; i += 5) { - e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 40; i < 60; i += 5) { - e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 60; i < 80; i += 5) { - e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30); - } - - val[0] += a; - val[1] += b; - val[2] += c; - val[3] += d; - val[4] += e; -} - -/* see bearssl.h */ -void -br_sha1_init(br_sha1_context *cc) -{ - cc->vtable = &br_sha1_vtable; - memcpy(cc->val, br_sha1_IV, sizeof cc->val); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_sha1_update(br_sha1_context *cc, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)cc->count & 63; - while (len > 0) { - size_t clen; - - clen = 64 - ptr; - if (clen > len) { - clen = len; - } - memcpy(cc->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - cc->count += (uint64_t)clen; - if (ptr == 64) { - br_sha1_round(cc->buf, cc->val); - ptr = 0; - } - } -} - -/* see bearssl.h */ -void -br_sha1_out(const br_sha1_context *cc, void *dst) -{ - unsigned char buf[64]; - uint32_t val[5]; - size_t ptr; - - ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); - buf[ptr ++] = 0x80; - if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); - br_sha1_round(buf, val); - memset(buf, 0, 56); - } else { - memset(buf + ptr, 0, 56 - ptr); - } - br_enc64be(buf + 56, cc->count << 3); - br_sha1_round(buf, val); - br_range_enc32be(dst, val, 5); -} - -/* see bearssl.h */ -uint64_t -br_sha1_state(const br_sha1_context *cc, void *dst) -{ - br_range_enc32be(dst, cc->val, 5); - return cc->count; -} - -/* see bearssl.h */ -void -br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count) -{ - br_range_dec32be(cc->val, 5, stb); - cc->count = count; -} - -/* see bearssl.h */ -const br_hash_class br_sha1_vtable = { - sizeof(br_sha1_context), - BR_HASHDESC_ID(br_sha1_ID) - | BR_HASHDESC_OUT(20) - | BR_HASHDESC_STATE(20) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **))&br_sha1_init, - (void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update, - (void (*)(const br_hash_class *const *, void *))&br_sha1_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_sha1_set_state -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/sha2big.c b/src/tls/bearssl/sha2big.c deleted file mode 100644 index 6ce516081..000000000 --- a/src/tls/bearssl/sha2big.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) -#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) - -#define ROTR(x, n) (((uint64_t)(x) << (64 - (n))) | ((uint64_t)(x) >> (n))) - -#define BSG5_0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) -#define BSG5_1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) -#define SSG5_0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (uint64_t)((x) >> 7)) -#define SSG5_1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (uint64_t)((x) >> 6)) - -static const uint64_t IV384[8] = { - 0xCBBB9D5DC1059ED8, 0x629A292A367CD507, - 0x9159015A3070DD17, 0x152FECD8F70E5939, - 0x67332667FFC00B31, 0x8EB44A8768581511, - 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4 -}; - -static const uint64_t IV512[8] = { - 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, - 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, - 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, - 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 -}; - -static const uint64_t K[80] = { - 0x428A2F98D728AE22, 0x7137449123EF65CD, - 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC, - 0x3956C25BF348B538, 0x59F111F1B605D019, - 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118, - 0xD807AA98A3030242, 0x12835B0145706FBE, - 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2, - 0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, - 0x9BDC06A725C71235, 0xC19BF174CF692694, - 0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, - 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65, - 0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, - 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5, - 0x983E5152EE66DFAB, 0xA831C66D2DB43210, - 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4, - 0xC6E00BF33DA88FC2, 0xD5A79147930AA725, - 0x06CA6351E003826F, 0x142929670A0E6E70, - 0x27B70A8546D22FFC, 0x2E1B21385C26C926, - 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF, - 0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, - 0x81C2C92E47EDAEE6, 0x92722C851482353B, - 0xA2BFE8A14CF10364, 0xA81A664BBC423001, - 0xC24B8B70D0F89791, 0xC76C51A30654BE30, - 0xD192E819D6EF5218, 0xD69906245565A910, - 0xF40E35855771202A, 0x106AA07032BBD1B8, - 0x19A4C116B8D2D0C8, 0x1E376C085141AB53, - 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8, - 0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, - 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3, - 0x748F82EE5DEFB2FC, 0x78A5636F43172F60, - 0x84C87814A1F0AB72, 0x8CC702081A6439EC, - 0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, - 0xBEF9A3F7B2C67915, 0xC67178F2E372532B, - 0xCA273ECEEA26619C, 0xD186B8C721C0C207, - 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178, - 0x06F067AA72176FBA, 0x0A637DC5A2C898A6, - 0x113F9804BEF90DAE, 0x1B710B35131C471B, - 0x28DB77F523047D84, 0x32CAAB7B40C72493, - 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C, - 0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, - 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817 -}; - -static void -sha2big_round(const unsigned char *buf, uint64_t *val) -{ - -#define SHA2BIG_STEP(A, B, C, D, E, F, G, H, j) do { \ - uint64_t T1, T2; \ - T1 = H + BSG5_1(E) + CH(E, F, G) + K[j] + w[j]; \ - T2 = BSG5_0(A) + MAJ(A, B, C); \ - D += T1; \ - H = T1 + T2; \ - } while (0) - - int i; - uint64_t a, b, c, d, e, f, g, h; - uint64_t w[80]; - - br_range_dec64be(w, 16, buf); - for (i = 16; i < 80; i ++) { - w[i] = SSG5_1(w[i - 2]) + w[i - 7] - + SSG5_0(w[i - 15]) + w[i - 16]; - } - a = val[0]; - b = val[1]; - c = val[2]; - d = val[3]; - e = val[4]; - f = val[5]; - g = val[6]; - h = val[7]; - for (i = 0; i < 80; i += 8) { - SHA2BIG_STEP(a, b, c, d, e, f, g, h, i + 0); - SHA2BIG_STEP(h, a, b, c, d, e, f, g, i + 1); - SHA2BIG_STEP(g, h, a, b, c, d, e, f, i + 2); - SHA2BIG_STEP(f, g, h, a, b, c, d, e, i + 3); - SHA2BIG_STEP(e, f, g, h, a, b, c, d, i + 4); - SHA2BIG_STEP(d, e, f, g, h, a, b, c, i + 5); - SHA2BIG_STEP(c, d, e, f, g, h, a, b, i + 6); - SHA2BIG_STEP(b, c, d, e, f, g, h, a, i + 7); - } - val[0] += a; - val[1] += b; - val[2] += c; - val[3] += d; - val[4] += e; - val[5] += f; - val[6] += g; - val[7] += h; -} - -static void -sha2big_update(br_sha384_context *cc, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)cc->count & 127; - cc->count += (uint64_t)len; - while (len > 0) { - size_t clen; - - clen = 128 - ptr; - if (clen > len) { - clen = len; - } - memcpy(cc->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - if (ptr == 128) { - sha2big_round(cc->buf, cc->val); - ptr = 0; - } - } -} - -static void -sha2big_out(const br_sha384_context *cc, void *dst, int num) -{ - unsigned char buf[128]; - uint64_t val[8]; - size_t ptr; - - ptr = (size_t)cc->count & 127; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); - buf[ptr ++] = 0x80; - if (ptr > 112) { - memset(buf + ptr, 0, 128 - ptr); - sha2big_round(buf, val); - memset(buf, 0, 112); - } else { - memset(buf + ptr, 0, 112 - ptr); - } - br_enc64be(buf + 112, cc->count >> 61); - br_enc64be(buf + 120, cc->count << 3); - sha2big_round(buf, val); - br_range_enc64be(dst, val, num); -} - -/* see bearssl.h */ -void -br_sha384_init(br_sha384_context *cc) -{ - cc->vtable = &br_sha384_vtable; - memcpy(cc->val, IV384, sizeof IV384); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_sha384_update(br_sha384_context *cc, const void *data, size_t len) -{ - sha2big_update(cc, data, len); -} - -/* see bearssl.h */ -void -br_sha384_out(const br_sha384_context *cc, void *dst) -{ - sha2big_out(cc, dst, 6); -} - -/* see bearssl.h */ -uint64_t -br_sha384_state(const br_sha384_context *cc, void *dst) -{ - br_range_enc64be(dst, cc->val, 8); - return cc->count; -} - -/* see bearssl.h */ -void -br_sha384_set_state(br_sha384_context *cc, const void *stb, uint64_t count) -{ - br_range_dec64be(cc->val, 8, stb); - cc->count = count; -} - -/* see bearssl.h */ -void -br_sha512_init(br_sha512_context *cc) -{ - cc->vtable = &br_sha512_vtable; - memcpy(cc->val, IV512, sizeof IV512); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_sha512_out(const br_sha512_context *cc, void *dst) -{ - sha2big_out(cc, dst, 8); -} - -/* see bearssl.h */ -const br_hash_class br_sha384_vtable = { - sizeof(br_sha384_context), - BR_HASHDESC_ID(br_sha384_ID) - | BR_HASHDESC_OUT(48) - | BR_HASHDESC_STATE(64) - | BR_HASHDESC_LBLEN(7) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE - | BR_HASHDESC_MD_PADDING_128, - (void (*)(const br_hash_class **))&br_sha384_init, - (void (*)(const br_hash_class **, const void *, size_t)) - &br_sha384_update, - (void (*)(const br_hash_class *const *, void *))&br_sha384_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_sha384_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_sha384_set_state -}; - -/* see bearssl.h */ -const br_hash_class br_sha512_vtable = { - sizeof(br_sha512_context), - BR_HASHDESC_ID(br_sha512_ID) - | BR_HASHDESC_OUT(64) - | BR_HASHDESC_STATE(64) - | BR_HASHDESC_LBLEN(7) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE - | BR_HASHDESC_MD_PADDING_128, - (void (*)(const br_hash_class **))&br_sha512_init, - (void (*)(const br_hash_class **, const void *, size_t)) - &br_sha512_update, - (void (*)(const br_hash_class *const *, void *))&br_sha512_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_sha512_set_state -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/sha2small.c b/src/tls/bearssl/sha2small.c deleted file mode 100644 index 04cc71f81..000000000 --- a/src/tls/bearssl/sha2small.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#if defined(BOARD_HAS_ECCX08) || defined(BOARD_HAS_OFFLOADED_ECCX08) || \ - defined(BOARD_HAS_SE050) || defined(ARDUINO_ARCH_ESP32) || \ - defined(ARDUINO_UNOR4_WIFI) - -#include "inner.h" - -#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) -#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) - -#define ROTR(x, n) (((uint32_t)(x) << (32 - (n))) | ((uint32_t)(x) >> (n))) - -#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) -#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) -#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ (uint32_t)((x) >> 3)) -#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ (uint32_t)((x) >> 10)) - -/* see inner.h */ -const uint32_t br_sha224_IV[8] = { - 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, - 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 -}; - -/* see inner.h */ -const uint32_t br_sha256_IV[8] = { - 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, - 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 -}; - -static const uint32_t K[64] = { - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 -}; - -/* see inner.h */ -void -br_sha2small_round(const unsigned char *buf, uint32_t *val) -{ - -#define SHA2_STEP(A, B, C, D, E, F, G, H, j) do { \ - uint32_t T1, T2; \ - T1 = H + BSG2_1(E) + CH(E, F, G) + K[j] + w[j]; \ - T2 = BSG2_0(A) + MAJ(A, B, C); \ - D += T1; \ - H = T1 + T2; \ - } while (0) - - int i; - uint32_t a, b, c, d, e, f, g, h; - uint32_t w[64]; - - br_range_dec32be(w, 16, buf); - for (i = 16; i < 64; i ++) { - w[i] = SSG2_1(w[i - 2]) + w[i - 7] - + SSG2_0(w[i - 15]) + w[i - 16]; - } - a = val[0]; - b = val[1]; - c = val[2]; - d = val[3]; - e = val[4]; - f = val[5]; - g = val[6]; - h = val[7]; - for (i = 0; i < 64; i += 8) { - SHA2_STEP(a, b, c, d, e, f, g, h, i + 0); - SHA2_STEP(h, a, b, c, d, e, f, g, i + 1); - SHA2_STEP(g, h, a, b, c, d, e, f, i + 2); - SHA2_STEP(f, g, h, a, b, c, d, e, i + 3); - SHA2_STEP(e, f, g, h, a, b, c, d, i + 4); - SHA2_STEP(d, e, f, g, h, a, b, c, i + 5); - SHA2_STEP(c, d, e, f, g, h, a, b, i + 6); - SHA2_STEP(b, c, d, e, f, g, h, a, i + 7); - } - val[0] += a; - val[1] += b; - val[2] += c; - val[3] += d; - val[4] += e; - val[5] += f; - val[6] += g; - val[7] += h; - -#if 0 -/* obsolete */ -#define SHA2_MEXP1(pc) do { \ - W[pc] = br_dec32be(buf + ((pc) << 2)); \ - } while (0) - -#define SHA2_MEXP2(pc) do { \ - W[(pc) & 0x0F] = SSG2_1(W[((pc) - 2) & 0x0F]) \ - + W[((pc) - 7) & 0x0F] \ - + SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]; \ - } while (0) - -#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, pc) do { \ - uint32_t t1, t2; \ - SHA2_MEXP ## n(pc); \ - t1 = h + BSG2_1(e) + CH(e, f, g) \ - + K[pcount + (pc)] + W[(pc) & 0x0F]; \ - t2 = BSG2_0(a) + MAJ(a, b, c); \ - d += t1; \ - h = t1 + t2; \ - } while (0) - -#define SHA2_STEP1(a, b, c, d, e, f, g, h, pc) \ - SHA2_STEPn(1, a, b, c, d, e, f, g, h, pc) -#define SHA2_STEP2(a, b, c, d, e, f, g, h, pc) \ - SHA2_STEPn(2, a, b, c, d, e, f, g, h, pc) - - uint32_t A, B, C, D, E, F, G, H; - uint32_t W[16]; - unsigned pcount; - - A = val[0]; - B = val[1]; - C = val[2]; - D = val[3]; - E = val[4]; - F = val[5]; - G = val[6]; - H = val[7]; - pcount = 0; - SHA2_STEP1(A, B, C, D, E, F, G, H, 0); - SHA2_STEP1(H, A, B, C, D, E, F, G, 1); - SHA2_STEP1(G, H, A, B, C, D, E, F, 2); - SHA2_STEP1(F, G, H, A, B, C, D, E, 3); - SHA2_STEP1(E, F, G, H, A, B, C, D, 4); - SHA2_STEP1(D, E, F, G, H, A, B, C, 5); - SHA2_STEP1(C, D, E, F, G, H, A, B, 6); - SHA2_STEP1(B, C, D, E, F, G, H, A, 7); - SHA2_STEP1(A, B, C, D, E, F, G, H, 8); - SHA2_STEP1(H, A, B, C, D, E, F, G, 9); - SHA2_STEP1(G, H, A, B, C, D, E, F, 10); - SHA2_STEP1(F, G, H, A, B, C, D, E, 11); - SHA2_STEP1(E, F, G, H, A, B, C, D, 12); - SHA2_STEP1(D, E, F, G, H, A, B, C, 13); - SHA2_STEP1(C, D, E, F, G, H, A, B, 14); - SHA2_STEP1(B, C, D, E, F, G, H, A, 15); - for (pcount = 16; pcount < 64; pcount += 16) { - SHA2_STEP2(A, B, C, D, E, F, G, H, 0); - SHA2_STEP2(H, A, B, C, D, E, F, G, 1); - SHA2_STEP2(G, H, A, B, C, D, E, F, 2); - SHA2_STEP2(F, G, H, A, B, C, D, E, 3); - SHA2_STEP2(E, F, G, H, A, B, C, D, 4); - SHA2_STEP2(D, E, F, G, H, A, B, C, 5); - SHA2_STEP2(C, D, E, F, G, H, A, B, 6); - SHA2_STEP2(B, C, D, E, F, G, H, A, 7); - SHA2_STEP2(A, B, C, D, E, F, G, H, 8); - SHA2_STEP2(H, A, B, C, D, E, F, G, 9); - SHA2_STEP2(G, H, A, B, C, D, E, F, 10); - SHA2_STEP2(F, G, H, A, B, C, D, E, 11); - SHA2_STEP2(E, F, G, H, A, B, C, D, 12); - SHA2_STEP2(D, E, F, G, H, A, B, C, 13); - SHA2_STEP2(C, D, E, F, G, H, A, B, 14); - SHA2_STEP2(B, C, D, E, F, G, H, A, 15); - } - val[0] += A; - val[1] += B; - val[2] += C; - val[3] += D; - val[4] += E; - val[5] += F; - val[6] += G; - val[7] += H; -#endif -} - -static void -sha2small_update(br_sha224_context *cc, const void *data, size_t len) -{ - const unsigned char *buf; - size_t ptr; - - buf = data; - ptr = (size_t)cc->count & 63; - cc->count += (uint64_t)len; - while (len > 0) { - size_t clen; - - clen = 64 - ptr; - if (clen > len) { - clen = len; - } - memcpy(cc->buf + ptr, buf, clen); - ptr += clen; - buf += clen; - len -= clen; - if (ptr == 64) { - br_sha2small_round(cc->buf, cc->val); - ptr = 0; - } - } -} - -static void -sha2small_out(const br_sha224_context *cc, void *dst, int num) -{ - unsigned char buf[64]; - uint32_t val[8]; - size_t ptr; - - ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); - buf[ptr ++] = 0x80; - if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); - br_sha2small_round(buf, val); - memset(buf, 0, 56); - } else { - memset(buf + ptr, 0, 56 - ptr); - } - br_enc64be(buf + 56, cc->count << 3); - br_sha2small_round(buf, val); - br_range_enc32be(dst, val, num); -} - -/* see bearssl.h */ -void -br_sha224_init(br_sha224_context *cc) -{ - cc->vtable = &br_sha224_vtable; - memcpy(cc->val, br_sha224_IV, sizeof cc->val); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_sha224_update(br_sha224_context *cc, const void *data, size_t len) -{ - sha2small_update(cc, data, len); -} - -/* see bearssl.h */ -void -br_sha224_out(const br_sha224_context *cc, void *dst) -{ - sha2small_out(cc, dst, 7); -} - -/* see bearssl.h */ -uint64_t -br_sha224_state(const br_sha224_context *cc, void *dst) -{ - br_range_enc32be(dst, cc->val, 8); - return cc->count; -} - -/* see bearssl.h */ -void -br_sha224_set_state(br_sha224_context *cc, const void *stb, uint64_t count) -{ - br_range_dec32be(cc->val, 8, stb); - cc->count = count; -} - -/* see bearssl.h */ -void -br_sha256_init(br_sha256_context *cc) -{ - cc->vtable = &br_sha256_vtable; - memcpy(cc->val, br_sha256_IV, sizeof cc->val); - cc->count = 0; -} - -/* see bearssl.h */ -void -br_sha256_out(const br_sha256_context *cc, void *dst) -{ - sha2small_out(cc, dst, 8); -} - -/* see bearssl.h */ -const br_hash_class br_sha224_vtable = { - sizeof(br_sha224_context), - BR_HASHDESC_ID(br_sha224_ID) - | BR_HASHDESC_OUT(28) - | BR_HASHDESC_STATE(32) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **))&br_sha224_init, - (void (*)(const br_hash_class **, - const void *, size_t))&br_sha224_update, - (void (*)(const br_hash_class *const *, void *))&br_sha224_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_sha224_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_sha224_set_state -}; - -/* see bearssl.h */ -const br_hash_class br_sha256_vtable = { - sizeof(br_sha256_context), - BR_HASHDESC_ID(br_sha256_ID) - | BR_HASHDESC_OUT(32) - | BR_HASHDESC_STATE(32) - | BR_HASHDESC_LBLEN(6) - | BR_HASHDESC_MD_PADDING - | BR_HASHDESC_MD_PADDING_BE, - (void (*)(const br_hash_class **))&br_sha256_init, - (void (*)(const br_hash_class **, - const void *, size_t))&br_sha256_update, - (void (*)(const br_hash_class *const *, void *))&br_sha256_out, - (uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state, - (void (*)(const br_hash_class **, const void *, uint64_t)) - &br_sha256_set_state -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/skey_decoder.c b/src/tls/bearssl/skey_decoder.c deleted file mode 100644 index 2b7d03a58..000000000 --- a/src/tls/bearssl/skey_decoder.c +++ /dev/null @@ -1,655 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_skey_decoder_init_main(void *t0ctx); - -void br_skey_decoder_run(void *t0ctx); - - - -#include "inner.h" - - - - - -#include "inner.h" - -#define CTX ((br_skey_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_skey_decoder_context, cpu))) -#define CONTEXT_NAME br_skey_decoder_context - -/* see bearssl_x509.h */ -void -br_skey_decoder_init(br_skey_decoder_context *ctx) -{ - memset(ctx, 0, sizeof *ctx); - ctx->cpu.dp = &ctx->dp_stack[0]; - ctx->cpu.rp = &ctx->rp_stack[0]; - br_skey_decoder_init_main(&ctx->cpu); - br_skey_decoder_run(&ctx->cpu); -} - -/* see bearssl_x509.h */ -void -br_skey_decoder_push(br_skey_decoder_context *ctx, - const void *data, size_t len) -{ - ctx->hbuf = data; - ctx->hlen = len; - br_skey_decoder_run(&ctx->cpu); -} - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x07, - 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, - 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B, - 0x81, 0x04, 0x00, 0x23 -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x01, 0x08, 0x00, 0x00, 0x13, - 0x13, 0x00, 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, - 0x01, T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INVALID_VALUE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, - T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), - 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_data)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_type)), 0x00, 0x00, - 0x33, 0x48, 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, pad)), - 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, 0x1C, 0x00, 0x00, 0x01, 0x22, - 0x00, 0x00, 0x05, 0x02, 0x2C, 0x16, 0x00, 0x00, 0x06, 0x02, 0x2D, 0x16, - 0x00, 0x00, 0x01, 0x10, 0x3D, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16, - 0x3A, 0x00, 0x00, 0x0D, 0x05, 0x02, 0x2F, 0x16, 0x3B, 0x00, 0x00, 0x06, - 0x02, 0x27, 0x16, 0x00, 0x01, 0x03, 0x00, 0x54, 0x57, 0x01, 0x02, 0x3E, - 0x55, 0x23, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x04, 0x3E, 0x02, 0x00, - 0x41, 0x3F, 0x00, 0x02, 0x03, 0x00, 0x53, 0x14, 0x14, 0x03, 0x01, 0x48, - 0x0E, 0x06, 0x02, 0x30, 0x16, 0x33, 0x4C, 0x58, 0x01, 0x7F, 0x19, 0x0D, - 0x06, 0x04, 0x13, 0x13, 0x04, 0x29, 0x01, 0x20, 0x19, 0x0D, 0x06, 0x16, - 0x13, 0x3A, 0x53, 0x4D, 0x02, 0x00, 0x06, 0x09, 0x02, 0x00, 0x0C, 0x06, - 0x02, 0x2A, 0x16, 0x04, 0x02, 0x03, 0x00, 0x3F, 0x04, 0x0D, 0x01, 0x21, - 0x19, 0x0D, 0x06, 0x04, 0x13, 0x3A, 0x04, 0x03, 0x30, 0x16, 0x13, 0x5D, - 0x02, 0x00, 0x05, 0x02, 0x30, 0x16, 0x02, 0x00, 0x02, 0x01, 0x1D, 0x00, - 0x02, 0x53, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x5B, 0x15, 0x06, 0x07, 0x5D, - 0x01, 0x7F, 0x03, 0x01, 0x04, 0x16, 0x46, 0x15, 0x06, 0x10, 0x01, 0x00, - 0x03, 0x01, 0x14, 0x06, 0x03, 0x4D, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, - 0x04, 0x02, 0x30, 0x16, 0x3F, 0x57, 0x01, 0x04, 0x3E, 0x53, 0x02, 0x01, - 0x06, 0x03, 0x43, 0x04, 0x03, 0x02, 0x00, 0x40, 0x3F, 0x5D, 0x02, 0x01, - 0x06, 0x03, 0x32, 0x04, 0x01, 0x31, 0x00, 0x00, 0x54, 0x57, 0x01, 0x02, - 0x3E, 0x55, 0x06, 0x02, 0x30, 0x16, 0x57, 0x01, 0x02, 0x3E, 0x44, 0x3F, - 0x00, 0x07, 0x35, 0x50, 0x14, 0x05, 0x02, 0x2F, 0x16, 0x23, 0x01, 0x03, - 0x0B, 0x33, 0x17, 0x47, 0x07, 0x03, 0x00, 0x4F, 0x4F, 0x35, 0x4E, 0x14, - 0x14, 0x03, 0x01, 0x03, 0x02, 0x51, 0x14, 0x03, 0x03, 0x02, 0x02, 0x07, - 0x14, 0x03, 0x02, 0x51, 0x14, 0x03, 0x04, 0x02, 0x02, 0x07, 0x14, 0x03, - 0x02, 0x51, 0x14, 0x03, 0x05, 0x02, 0x02, 0x07, 0x14, 0x03, 0x02, 0x51, - 0x03, 0x06, 0x02, 0x00, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, - 0x02, 0x06, 0x1E, 0x00, 0x00, 0x19, 0x19, 0x00, 0x00, 0x01, 0x0B, 0x00, - 0x00, 0x01, 0x00, 0x20, 0x14, 0x06, 0x08, 0x01, 0x01, 0x21, 0x20, 0x22, - 0x20, 0x04, 0x75, 0x13, 0x00, 0x00, 0x01, - T0_INT2(3 * BR_X509_BUFSIZE_KEY), 0x00, 0x01, 0x01, 0x87, 0xFF, 0xFF, - 0x7F, 0x54, 0x57, 0x01, 0x02, 0x3E, 0x55, 0x01, 0x01, 0x0E, 0x06, 0x02, - 0x30, 0x16, 0x57, 0x01, 0x02, 0x19, 0x0D, 0x06, 0x06, 0x13, 0x3B, 0x44, - 0x32, 0x04, 0x1C, 0x01, 0x04, 0x19, 0x0D, 0x06, 0x08, 0x13, 0x3B, 0x01, - 0x00, 0x41, 0x31, 0x04, 0x0E, 0x01, 0x10, 0x19, 0x0D, 0x06, 0x05, 0x13, - 0x3A, 0x42, 0x04, 0x03, 0x30, 0x16, 0x13, 0x03, 0x00, 0x3F, 0x02, 0x00, - 0x34, 0x1F, 0x5A, 0x27, 0x16, 0x00, 0x01, 0x45, 0x0A, 0x06, 0x02, 0x29, - 0x16, 0x14, 0x03, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x57, 0x01, 0x06, - 0x3E, 0x56, 0x00, 0x00, 0x20, 0x14, 0x06, 0x07, 0x1A, 0x14, 0x06, 0x01, - 0x12, 0x04, 0x76, 0x24, 0x00, 0x00, 0x4B, 0x05, 0x02, 0x30, 0x16, 0x37, - 0x15, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x38, 0x15, 0x06, 0x04, 0x01, - 0x18, 0x04, 0x0A, 0x39, 0x15, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x30, - 0x16, 0x00, 0x00, 0x1C, 0x57, 0x01, 0x02, 0x3E, 0x09, 0x50, 0x00, 0x00, - 0x35, 0x4E, 0x13, 0x00, 0x03, 0x14, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, - 0x53, 0x59, 0x14, 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x14, - 0x01, 0x00, 0x0D, 0x06, 0x0B, 0x13, 0x14, 0x05, 0x04, 0x13, 0x01, 0x00, - 0x00, 0x59, 0x04, 0x6F, 0x02, 0x01, 0x14, 0x05, 0x02, 0x2B, 0x16, 0x23, - 0x03, 0x01, 0x02, 0x02, 0x1F, 0x02, 0x02, 0x22, 0x03, 0x02, 0x14, 0x06, - 0x03, 0x59, 0x04, 0x68, 0x13, 0x02, 0x00, 0x02, 0x01, 0x08, 0x00, 0x00, - 0x14, 0x35, 0x1C, 0x08, 0x20, 0x1C, 0x07, 0x20, 0x4E, 0x00, 0x01, 0x59, - 0x14, 0x01, 0x81, 0x00, 0x0A, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x08, - 0x14, 0x05, 0x02, 0x28, 0x16, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, - 0x00, 0x0E, 0x06, 0x19, 0x02, 0x00, 0x23, 0x03, 0x00, 0x14, 0x01, 0x83, - 0xFF, 0xFF, 0x7F, 0x0E, 0x06, 0x02, 0x29, 0x16, 0x01, 0x08, 0x0B, 0x20, - 0x59, 0x1C, 0x07, 0x04, 0x60, 0x00, 0x00, 0x52, 0x4A, 0x00, 0x00, 0x57, - 0x3C, 0x53, 0x00, 0x01, 0x53, 0x14, 0x05, 0x02, 0x2E, 0x16, 0x59, 0x14, - 0x01, 0x81, 0x00, 0x0F, 0x06, 0x02, 0x2E, 0x16, 0x03, 0x00, 0x14, 0x06, - 0x16, 0x59, 0x02, 0x00, 0x14, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x0F, 0x06, - 0x02, 0x2E, 0x16, 0x01, 0x08, 0x0B, 0x07, 0x03, 0x00, 0x04, 0x67, 0x13, - 0x02, 0x00, 0x00, 0x00, 0x53, 0x14, 0x01, 0x81, 0x7F, 0x0E, 0x06, 0x08, - 0x5C, 0x01, 0x00, 0x36, 0x1F, 0x01, 0x00, 0x00, 0x14, 0x36, 0x1F, 0x36, - 0x22, 0x4C, 0x01, 0x7F, 0x00, 0x01, 0x59, 0x03, 0x00, 0x02, 0x00, 0x01, - 0x05, 0x10, 0x01, 0x01, 0x11, 0x18, 0x02, 0x00, 0x01, 0x06, 0x10, 0x14, - 0x01, 0x01, 0x11, 0x06, 0x02, 0x25, 0x16, 0x01, 0x04, 0x0B, 0x02, 0x00, - 0x01, 0x1F, 0x11, 0x14, 0x01, 0x1F, 0x0D, 0x06, 0x02, 0x26, 0x16, 0x07, - 0x00, 0x00, 0x14, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x57, 0x00, - 0x00, 0x14, 0x05, 0x02, 0x29, 0x16, 0x23, 0x5A, 0x00, 0x00, 0x1B, 0x14, - 0x01, 0x00, 0x0F, 0x06, 0x01, 0x00, 0x13, 0x12, 0x04, 0x74, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x5D, 0x13, 0x00, 0x00, 0x14, 0x06, 0x07, 0x5E, 0x14, - 0x06, 0x01, 0x12, 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x19, 0x1A, 0x09, - 0x24, 0x00 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 14, - 18, - 22, - 26, - 30, - 34, - 38, - 42, - 46, - 50, - 54, - 58, - 62, - 66, - 70, - 75, - 80, - 84, - 89, - 93, - 97, - 101, - 107, - 113, - 118, - 126, - 134, - 140, - 163, - 244, - 311, - 329, - 404, - 408, - 412, - 429, - 434, - 505, - 519, - 526, - 540, - 573, - 582, - 587, - 654, - 665, - 721, - 725, - 730, - 778, - 804, - 848, - 859, - 868, - 881, - 885, - 889, - 901 -}; - -#define T0_INTERPRETED 34 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_skey_decoder_init_main, 73) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_skey_decoder_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 8: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 9: { - /* -rot */ - T0_NROT(); - } - break; - case 10: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 11: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 12: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 13: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 14: { - /* > */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a > b)); - - } - break; - case 15: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 16: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 17: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 18: { - /* co */ - T0_CO(); - } - break; - case 19: { - /* drop */ - (void)T0_POP(); - } - break; - case 20: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 21: { - /* eqOID */ - - const unsigned char *a2 = &t0_datablock[T0_POP()]; - const unsigned char *a1 = &CTX->pad[0]; - size_t len = a1[0]; - int x; - if (len == a2[0]) { - x = -(memcmp(a1 + 1, a2 + 1, len) == 0); - } else { - x = 0; - } - T0_PUSH((uint32_t)x); - - } - break; - case 22: { - /* fail */ - - CTX->err = T0_POPi(); - T0_CO(); - - } - break; - case 23: { - /* get8 */ - - uint32_t addr = T0_POP(); - T0_PUSH(*((unsigned char *)CTX + addr)); - - } - break; - case 24: { - /* neg */ - - uint32_t a = T0_POP(); - T0_PUSH(-a); - - } - break; - case 25: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 26: { - /* read-blob-inner */ - - uint32_t len = T0_POP(); - uint32_t addr = T0_POP(); - size_t clen = CTX->hlen; - if (clen > len) { - clen = (size_t)len; - } - if (addr != 0) { - memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); - } - CTX->hbuf += clen; - CTX->hlen -= clen; - T0_PUSH(addr + clen); - T0_PUSH(len - clen); - - } - break; - case 27: { - /* read8-low */ - - if (CTX->hlen == 0) { - T0_PUSHi(-1); - } else { - CTX->hlen --; - T0_PUSH(*CTX->hbuf ++); - } - - } - break; - case 28: { - /* rot */ - T0_ROT(); - } - break; - case 29: { - /* set-ec-key */ - - size_t xlen = T0_POP(); - uint32_t curve = T0_POP(); - CTX->key.ec.curve = curve; - CTX->key.ec.x = CTX->key_data; - CTX->key.ec.xlen = xlen; - - } - break; - case 30: { - /* set-rsa-key */ - - size_t iqlen = T0_POP(); - size_t dqlen = T0_POP(); - size_t dplen = T0_POP(); - size_t qlen = T0_POP(); - size_t plen = T0_POP(); - uint32_t n_bitlen = T0_POP(); - size_t off; - - CTX->key.rsa.n_bitlen = n_bitlen; - CTX->key.rsa.p = CTX->key_data; - CTX->key.rsa.plen = plen; - off = plen; - CTX->key.rsa.q = CTX->key_data + off; - CTX->key.rsa.qlen = qlen; - off += qlen; - CTX->key.rsa.dp = CTX->key_data + off; - CTX->key.rsa.dplen = dplen; - off += dplen; - CTX->key.rsa.dq = CTX->key_data + off; - CTX->key.rsa.dqlen = dqlen; - off += dqlen; - CTX->key.rsa.iq = CTX->key_data + off; - CTX->key.rsa.iqlen = iqlen; - - } - break; - case 31: { - /* set8 */ - - uint32_t addr = T0_POP(); - *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); - - } - break; - case 32: { - /* swap */ - T0_SWAP(); - } - break; - case 33: { - /* u>> */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x >> c); - - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_ccert_single_ec.c b/src/tls/bearssl/ssl_ccert_single_ec.c deleted file mode 100644 index d18d165e6..000000000 --- a/src/tls/bearssl/ssl_ccert_single_ec.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static void -cc_none0(const br_ssl_client_certificate_class **pctx) -{ - (void)pctx; -} - -static void -cc_none1(const br_ssl_client_certificate_class **pctx, size_t len) -{ - (void)pctx; - (void)len; -} - -static void -cc_none2(const br_ssl_client_certificate_class **pctx, - const unsigned char *data, size_t len) -{ - (void)pctx; - (void)data; - (void)len; -} - -static void -cc_choose(const br_ssl_client_certificate_class **pctx, - const br_ssl_client_context *cc, uint32_t auth_types, - br_ssl_client_certificate *choices) -{ - br_ssl_client_certificate_ec_context *zc; - int x; - int scurve; - - zc = (br_ssl_client_certificate_ec_context *)pctx; - scurve = br_ssl_client_get_server_curve(cc); - - if ((zc->allowed_usages & BR_KEYTYPE_KEYX) != 0 - && scurve == zc->sk->curve) - { - int x; - - x = (zc->issuer_key_type == BR_KEYTYPE_RSA) ? 16 : 17; - if (((auth_types >> x) & 1) != 0) { - choices->auth_type = BR_AUTH_ECDH; - choices->hash_id = -1; - choices->chain = zc->chain; - choices->chain_len = zc->chain_len; - } - } - - /* - * For ECDSA authentication, we must choose an appropriate - * hash function. - */ - x = br_ssl_choose_hash((unsigned)(auth_types >> 8)); - if (x == 0 || (zc->allowed_usages & BR_KEYTYPE_SIGN) == 0) { - memset(choices, 0, sizeof *choices); - return; - } - choices->auth_type = BR_AUTH_ECDSA; - choices->hash_id = x; - choices->chain = zc->chain; - choices->chain_len = zc->chain_len; -} - -static uint32_t -cc_do_keyx(const br_ssl_client_certificate_class **pctx, - unsigned char *data, size_t *len) -{ - br_ssl_client_certificate_ec_context *zc; - uint32_t r; - size_t xoff, xlen; - - zc = (br_ssl_client_certificate_ec_context *)pctx; - r = zc->iec->mul(data, *len, zc->sk->x, zc->sk->xlen, zc->sk->curve); - xoff = zc->iec->xoff(zc->sk->curve, &xlen); - memmove(data, data + xoff, xlen); - *len = xlen; - return r; -} - -static size_t -cc_do_sign(const br_ssl_client_certificate_class **pctx, - int hash_id, size_t hv_len, unsigned char *data, size_t len) -{ - br_ssl_client_certificate_ec_context *zc; - unsigned char hv[64]; - const br_hash_class *hc; - - zc = (br_ssl_client_certificate_ec_context *)pctx; - memcpy(hv, data, hv_len); - hc = br_multihash_getimpl(zc->mhash, hash_id); - if (hc == NULL) { - return 0; - } - if (len < 139) { - return 0; - } - return zc->iecdsa(zc->iec, hc, hv, zc->sk, data); -} - -static const br_ssl_client_certificate_class ccert_vtable = { - sizeof(br_ssl_client_certificate_ec_context), - cc_none0, /* start_name_list */ - cc_none1, /* start_name */ - cc_none2, /* append_name */ - cc_none0, /* end_name */ - cc_none0, /* end_name_list */ - cc_choose, - cc_do_keyx, - cc_do_sign -}; - -/* see bearssl_ssl.h */ -void -br_ssl_client_set_single_ec(br_ssl_client_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk, unsigned allowed_usages, - unsigned cert_issuer_key_type, - const br_ec_impl *iec, br_ecdsa_sign iecdsa) -{ - cc->client_auth.single_ec.vtable = &ccert_vtable; - cc->client_auth.single_ec.chain = chain; - cc->client_auth.single_ec.chain_len = chain_len; - cc->client_auth.single_ec.sk = sk; - cc->client_auth.single_ec.allowed_usages = allowed_usages; - cc->client_auth.single_ec.issuer_key_type = cert_issuer_key_type; - cc->client_auth.single_ec.mhash = &cc->eng.mhash; - cc->client_auth.single_ec.iec = iec; - cc->client_auth.single_ec.iecdsa = iecdsa; - cc->client_auth_vtable = &cc->client_auth.single_ec.vtable; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_ccert_single_rsa.c b/src/tls/bearssl/ssl_ccert_single_rsa.c deleted file mode 100644 index 713095f2a..000000000 --- a/src/tls/bearssl/ssl_ccert_single_rsa.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static void -cc_none0(const br_ssl_client_certificate_class **pctx) -{ - (void)pctx; -} - -static void -cc_none1(const br_ssl_client_certificate_class **pctx, size_t len) -{ - (void)pctx; - (void)len; -} - -static void -cc_none2(const br_ssl_client_certificate_class **pctx, - const unsigned char *data, size_t len) -{ - (void)pctx; - (void)data; - (void)len; -} - -static void -cc_choose(const br_ssl_client_certificate_class **pctx, - const br_ssl_client_context *cc, uint32_t auth_types, - br_ssl_client_certificate *choices) -{ - br_ssl_client_certificate_rsa_context *zc; - int x; - - (void)cc; - zc = (br_ssl_client_certificate_rsa_context *)pctx; - x = br_ssl_choose_hash((unsigned)auth_types); - if (x == 0 && (auth_types & 1) == 0) { - memset(choices, 0, sizeof *choices); - } - choices->auth_type = BR_AUTH_RSA; - choices->hash_id = x; - choices->chain = zc->chain; - choices->chain_len = zc->chain_len; -} - -/* - * OID for hash functions in RSA signatures. - */ -static const unsigned char HASH_OID_SHA1[] = { - 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A -}; - -static const unsigned char HASH_OID_SHA224[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 -}; - -static const unsigned char HASH_OID_SHA256[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 -}; - -static const unsigned char HASH_OID_SHA384[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 -}; - -static const unsigned char HASH_OID_SHA512[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 -}; - -static const unsigned char *HASH_OID[] = { - HASH_OID_SHA1, - HASH_OID_SHA224, - HASH_OID_SHA256, - HASH_OID_SHA384, - HASH_OID_SHA512 -}; - -static size_t -cc_do_sign(const br_ssl_client_certificate_class **pctx, - int hash_id, size_t hv_len, unsigned char *data, size_t len) -{ - br_ssl_client_certificate_rsa_context *zc; - unsigned char hv[64]; - const unsigned char *hash_oid; - size_t sig_len; - - zc = (br_ssl_client_certificate_rsa_context *)pctx; - memcpy(hv, data, hv_len); - if (hash_id == 0) { - hash_oid = NULL; - } else if (hash_id >= 2 && hash_id <= 6) { - hash_oid = HASH_OID[hash_id - 2]; - } else { - return 0; - } - sig_len = (zc->sk->n_bitlen + 7) >> 3; - if (len < sig_len) { - return 0; - } - return zc->irsasign(hash_oid, hv, hv_len, zc->sk, data) ? sig_len : 0; -} - -static const br_ssl_client_certificate_class ccert_vtable = { - sizeof(br_ssl_client_certificate_rsa_context), - cc_none0, /* start_name_list */ - cc_none1, /* start_name */ - cc_none2, /* append_name */ - cc_none0, /* end_name */ - cc_none0, /* end_name_list */ - cc_choose, - 0, - cc_do_sign -}; - -/* see bearssl_ssl.h */ -void -br_ssl_client_set_single_rsa(br_ssl_client_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign) -{ - cc->client_auth.single_rsa.vtable = &ccert_vtable; - cc->client_auth.single_rsa.chain = chain; - cc->client_auth.single_rsa.chain_len = chain_len; - cc->client_auth.single_rsa.sk = sk; - cc->client_auth.single_rsa.irsasign = irsasign; - cc->client_auth_vtable = &cc->client_auth.single_rsa.vtable; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_client.c b/src/tls/bearssl/ssl_client.c deleted file mode 100644 index ccb9f6e08..000000000 --- a/src/tls/bearssl/ssl_client.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_client_zero(br_ssl_client_context *cc) -{ - /* - * For really standard C, we should explicitly set to NULL all - * pointers, and 0 all other fields. However, on all our target - * architectures, a direct memset() will work, be faster, and - * use a lot less code. - */ - memset(cc, 0, sizeof *cc); -} - -/* see bearssl_ssl.h */ -int -br_ssl_client_reset(br_ssl_client_context *cc, - const char *server_name, int resume_session) -{ - size_t n; - - br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0); - cc->eng.version_out = cc->eng.version_min; - if (!resume_session) { - br_ssl_client_forget_session(cc); - } - if (!br_ssl_engine_init_rand(&cc->eng)) { - return 0; - } - - /* - * We always set back the "reneg" flag to 0 because we use it - * to distinguish between first handshake and renegotiation. - * Note that "renegotiation" and "session resumption" are two - * different things. - */ - cc->eng.reneg = 0; - - if (server_name == NULL) { - cc->eng.server_name[0] = 0; - } else { - n = strlen(server_name) + 1; - if (n > sizeof cc->eng.server_name) { - br_ssl_engine_fail(&cc->eng, BR_ERR_BAD_PARAM); - return 0; - } - memcpy(cc->eng.server_name, server_name, n); - } - - br_ssl_engine_hs_reset(&cc->eng, - br_ssl_hs_client_init_main, br_ssl_hs_client_run); - return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_client_default_rsapub.c b/src/tls/bearssl/ssl_client_default_rsapub.c deleted file mode 100644 index f87a61595..000000000 --- a/src/tls/bearssl/ssl_client_default_rsapub.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_client_set_default_rsapub(br_ssl_client_context *cc) -{ - br_ssl_client_set_rsapub(cc, br_rsa_public_get_default()); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_client_full.c b/src/tls/bearssl/ssl_client_full.c deleted file mode 100644 index e64ad08b6..000000000 --- a/src/tls/bearssl/ssl_client_full.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_client_init_full(br_ssl_client_context *cc, - br_x509_minimal_context *xc, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) -{ - /* - * The "full" profile supports all implemented cipher suites. - * - * Rationale for suite order, from most important to least - * important rule: - * - * -- Don't use 3DES if AES or ChaCha20 is available. - * -- Try to have Forward Secrecy (ECDHE suite) if possible. - * -- When not using Forward Secrecy, ECDH key exchange is - * better than RSA key exchange (slightly more expensive on the - * client, but much cheaper on the server, and it implies smaller - * messages). - * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller code). - * -- GCM is better than CCM and CBC. CCM is better than CBC. - * -- CCM is preferable over CCM_8 (with CCM_8, forgeries may succeed - * with probability 2^(-64)). - * -- AES-128 is preferred over AES-256 (AES-128 is already - * strong enough, and AES-256 is 40% more expensive). - */ - static const uint16_t suites[] = { - BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_RSA_WITH_AES_128_CCM, - BR_TLS_RSA_WITH_AES_256_CCM, - BR_TLS_RSA_WITH_AES_128_CCM_8, - BR_TLS_RSA_WITH_AES_256_CCM_8, - BR_TLS_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_RSA_WITH_AES_256_CBC_SHA256, - BR_TLS_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA - }; - - /* - * All hash functions are activated. - * Note: the X.509 validation engine will nonetheless refuse to - * validate signatures that use MD5 as hash function. - */ - static const br_hash_class *hashes[] = { - &br_md5_vtable, - &br_sha1_vtable, - &br_sha224_vtable, - &br_sha256_vtable, - &br_sha384_vtable, - &br_sha512_vtable - }; - - int id; - - /* - * Reset client context and set supported versions from TLS-1.0 - * to TLS-1.2 (inclusive). - */ - br_ssl_client_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); - - /* - * X.509 engine uses SHA-256 to hash certificate DN (for - * comparisons). - */ - br_x509_minimal_init(xc, &br_sha256_vtable, - trust_anchors, trust_anchors_num); - - /* - * Set suites and asymmetric crypto implementations. We use the - * "i31" code for RSA (it is somewhat faster than the "i32" - * implementation). - * TODO: change that when better implementations are made available. - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_client_set_default_rsapub(cc); - br_ssl_engine_set_default_rsavrfy(&cc->eng); - br_ssl_engine_set_default_ecdsa(&cc->eng); - br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng)); - br_x509_minimal_set_ecdsa(xc, - br_ssl_engine_get_ec(&cc->eng), - br_ssl_engine_get_ecdsa(&cc->eng)); - - /* - * Set supported hash functions, for the SSL engine and for the - * X.509 engine. - */ - for (id = br_md5_ID; id <= br_sha512_ID; id ++) { - const br_hash_class *hc; - - hc = hashes[id - 1]; - br_ssl_engine_set_hash(&cc->eng, id, hc); - br_x509_minimal_set_hash(xc, id, hc); - } - - /* - * Link the X.509 engine in the SSL engine. - */ - br_ssl_engine_set_x509(&cc->eng, &xc->vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); - - /* - * Symmetric encryption. We use the "default" implementations - * (fastest among constant-time implementations). - */ - br_ssl_engine_set_default_aes_cbc(&cc->eng); - br_ssl_engine_set_default_aes_ccm(&cc->eng); - br_ssl_engine_set_default_aes_gcm(&cc->eng); - br_ssl_engine_set_default_des_cbc(&cc->eng); - br_ssl_engine_set_default_chapol(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine.c b/src/tls/bearssl/ssl_engine.c deleted file mode 100644 index d36ba9ddf..000000000 --- a/src/tls/bearssl/ssl_engine.c +++ /dev/null @@ -1,1574 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -#if 0 -/* obsolete */ - -/* - * If BR_USE_URANDOM is not defined, then try to autodetect its presence - * through compiler macros. - */ -#ifndef BR_USE_URANDOM - -/* - * Macro values documented on: - * https://sourceforge.net/p/predef/wiki/OperatingSystems/ - * - * Only the most common systems have been included here for now. This - * should be enriched later on. - */ -#if defined _AIX \ - || defined __ANDROID__ \ - || defined __FreeBSD__ \ - || defined __NetBSD__ \ - || defined __OpenBSD__ \ - || defined __DragonFly__ \ - || defined __linux__ \ - || (defined __sun && (defined __SVR4 || defined __svr4__)) \ - || (defined __APPLE__ && defined __MACH__) -#define BR_USE_URANDOM 1 -#endif - -#endif - -/* - * If BR_USE_WIN32_RAND is not defined, perform autodetection here. - */ -#ifndef BR_USE_WIN32_RAND - -#if defined _WIN32 || defined _WIN64 -#define BR_USE_WIN32_RAND 1 -#endif - -#endif - -#if BR_USE_URANDOM -#include -#include -#include -#include -#endif - -#if BR_USE_WIN32_RAND -#include -#include -#pragma comment(lib, "advapi32") -#endif - -#endif - -/* ==================================================================== */ -/* - * This part of the file does the low-level record management. - */ - -/* - * IMPLEMENTATION NOTES - * ==================== - * - * In this file, we designate by "input" (and the "i" letter) the "recv" - * operations: incoming records from the peer, from which payload data - * is obtained, and must be extracted by the application (or the SSL - * handshake engine). Similarly, "output" (and the "o" letter) is for - * "send": payload data injected by the application (and SSL handshake - * engine), to be wrapped into records, that are then conveyed to the - * peer over the transport medium. - * - * The input and output buffers may be distinct or shared. When - * shared, input and output cannot occur concurrently; the caller - * must make sure that it never needs to output data while input - * data has been received. In practice, a shared buffer prevents - * pipelining of HTTP requests, or similar protocols; however, a - * shared buffer saves RAM. - * - * The input buffer is pointed to by 'ibuf' and has size 'ibuf_len'; - * the output buffer is pointed to by 'obuf' and has size 'obuf_len'. - * From the size of these buffers is derived the maximum fragment - * length, which will be honoured upon sending records; regardless of - * that length, incoming records will be processed as long as they - * fit in the input buffer, and their length still complies with the - * protocol specification (maximum plaintext payload length is 16384 - * bytes). - * - * Three registers are used to manage buffering in ibuf, called ixa, - * ixb and ixc. Similarly, three registers are used to manage buffering - * in obuf, called oxa, oxb and oxc. - * - * - * At any time, the engine is in one of the following modes: - * -- Failed mode: an error occurs, no I/O can happen. - * -- Input mode: the engine can either receive record bytes from the - * transport layer, or it has some buffered payload bytes to yield. - * -- Output mode: the engine can either receive payload bytes, or it - * has some record bytes to send to the transport layer. - * -- Input/Output mode: both input and output modes are active. When - * the buffer is shared, this can happen only when the buffer is empty - * (no buffered payload bytes or record bytes in either direction). - * - * - * Failed mode: - * ------------ - * - * I/O failed for some reason (invalid received data, not enough room - * for the next record...). No I/O may ever occur again for this context, - * until an explicit reset is performed. This mode, and the error code, - * are also used for protocol errors, especially handshake errors. - * - * - * Input mode: - * ----------- - * - * ixa index within ibuf[] for the currently read data - * ixb maximum index within ibuf[] for the currently read data - * ixc number of bytes not yet received for the current record - * - * -- When ixa == ixb, there is no available data for readers. When - * ixa != ixb, there is available data and it starts at offset ixa. - * - * -- When waiting for the next record header, ixa and ixb are equal - * and contain a value ranging from 0 to 4; ixc is equal to 5-ixa. - * - * -- When the header has been received, record data is obtained. The - * ixc field records how many bytes are still needed to reach the - * end of the current record. - * - * ** If encryption is active, then ixa and ixb are kept equal, and - * point to the end of the currently received record bytes. When - * ixc reaches 0, decryption/MAC is applied, and ixa and ixb are - * adjusted. - * - * ** If encryption is not active, then ixa and ixb are distinct - * and data can be read right away. Additional record data is - * obtained only when ixa == ixb. - * - * Note: in input mode and no encryption, records larger than the buffer - * size are allowed. When encryption is active, the complete record must - * fit within the buffer, since it cannot be decrypted/MACed until it - * has been completely received. - * - * -- When receiving the next record header, 'version_in' contains the - * expected input version (0 if not expecting a specific version); on - * mismatch, the mode switches to 'failed'. - * - * -- When the header has been received, 'version_in' contains the received - * version. It is up to the caller to check and adjust the 'version_in' field - * to implement the required semantics. - * - * -- The 'record_type_in' field is updated with the incoming record type - * when the next record header has been received. - * - * - * Output mode: - * ------------ - * - * oxa index within obuf[] for the currently accumulated data - * oxb maximum index within obuf[] for record data - * oxc pointer for start of record data, and for record sending - * - * -- When oxa != oxb, more data can be accumulated into the current - * record; when oxa == oxb, a closed record is being sent. - * - * -- When accumulating data, oxc points to the start of the data. - * - * -- During record sending, oxa (and oxb) point to the next record byte - * to send, and oxc indicates the end of the current record. - * - * Note: sent records must fit within the buffer, since the header is - * adjusted only when the complete record has been assembled. - * - * -- The 'version_out' and 'record_type_out' fields are used to build the - * record header when the mode is switched to 'sending'. - * - * - * Modes: - * ------ - * - * The state register iomode contains one of the following values: - * - * BR_IO_FAILED I/O failed - * BR_IO_IN input mode - * BR_IO_OUT output mode - * BR_IO_INOUT input/output mode - * - * Whether encryption is active on incoming records is indicated by the - * incrypt flag. For outgoing records, there is no such flag; "encryption" - * is always considered active, but initially uses functions that do not - * encrypt anything. The 'incrypt' flag is needed because when there is - * no active encryption, records larger than the I/O buffer are accepted. - * - * Note: we do not support no-encryption modes (MAC only). - * - * TODO: implement GCM support - * - * - * Misc: - * ----- - * - * 'max_frag_len' is the maximum plaintext size for an outgoing record. - * By default, it is set to the maximum value that fits in the provided - * buffers, in the following list: 512, 1024, 2048, 4096, 16384. The - * caller may change it if needed, but the new value MUST still fit in - * the buffers, and it MUST be one of the list above for compatibility - * with the Maximum Fragment Length extension. - * - * For incoming records, only the total buffer length and current - * encryption mode impact the maximum length for incoming records. The - * 'max_frag_len' value is still adjusted so that records up to that - * length can be both received and sent. - * - * - * Offsets and lengths: - * -------------------- - * - * When sending fragments with TLS-1.1+, the maximum overhead is: - * 5 bytes for the record header - * 16 bytes for the explicit IV - * 48 bytes for the MAC (HMAC/SHA-384) - * 16 bytes for the padding (AES) - * so a total of 85 extra bytes. Note that we support block cipher sizes - * up to 16 bytes (AES) and HMAC output sizes up to 48 bytes (SHA-384). - * - * With TLS-1.0 and CBC mode, we apply a 1/n-1 split, for a maximum - * overhead of: - * 5 bytes for the first record header - * 32 bytes for the first record payload (AES-CBC + HMAC/SHA-1) - * 5 bytes for the second record header - * 20 bytes for the MAC (HMAC/SHA-1) - * 16 bytes for the padding (AES) - * -1 byte to account for the payload byte in the first record - * so a total of 77 extra bytes at most, less than the 85 bytes above. - * Note that with TLS-1.0, the MAC is HMAC with either MD5 or SHA-1, but - * no other hash function. - * - * The implementation does not try to send larger records when the current - * encryption mode has less overhead. - * - * Maximum input record overhead is: - * 5 bytes for the record header - * 16 bytes for the explicit IV (TLS-1.1+) - * 48 bytes for the MAC (HMAC/SHA-384) - * 256 bytes for the padding - * so a total of 325 extra bytes. - * - * When receiving the next record header, it is written into the buffer - * bytes 0 to 4 (inclusive). Record data is always written into buf[] - * starting at offset 5. When encryption is active, the plaintext data - * may start at a larger offset (e.g. because of an explicit IV). - */ - -#define MAX_OUT_OVERHEAD 85 -#define MAX_IN_OVERHEAD 325 - -/* see inner.h */ -void -br_ssl_engine_fail(br_ssl_engine_context *rc, int err) -{ - if (rc->iomode != BR_IO_FAILED) { - rc->iomode = BR_IO_FAILED; - rc->err = err; - } -} - -/* - * Adjust registers for a new incoming record. - */ -static void -make_ready_in(br_ssl_engine_context *rc) -{ - rc->ixa = rc->ixb = 0; - rc->ixc = 5; - if (rc->iomode == BR_IO_IN) { - rc->iomode = BR_IO_INOUT; - } -} - -/* - * Adjust registers for a new outgoing record. - */ -static void -make_ready_out(br_ssl_engine_context *rc) -{ - size_t a, b; - - a = 5; - b = rc->obuf_len - a; - rc->out.vtable->max_plaintext(&rc->out.vtable, &a, &b); - if ((b - a) > rc->max_frag_len) { - b = a + rc->max_frag_len; - } - rc->oxa = a; - rc->oxb = b; - rc->oxc = a; - if (rc->iomode == BR_IO_OUT) { - rc->iomode = BR_IO_INOUT; - } -} - -/* see inner.h */ -void -br_ssl_engine_new_max_frag_len(br_ssl_engine_context *rc, unsigned max_frag_len) -{ - size_t nxb; - - rc->max_frag_len = max_frag_len; - nxb = rc->oxc + max_frag_len; - if (rc->oxa < rc->oxb && rc->oxb > nxb && rc->oxa < nxb) { - rc->oxb = nxb; - } -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_buffer(br_ssl_engine_context *rc, - void *buf, size_t buf_len, int bidi) -{ - if (buf == NULL) { - br_ssl_engine_set_buffers_bidi(rc, NULL, 0, NULL, 0); - } else { - /* - * In bidirectional mode, we want to maximise input - * buffer size, since we support arbitrary fragmentation - * when sending, but the peer will not necessarily - * comply to any low fragment length (in particular if - * we are the server, because the maximum fragment - * length extension is under client control). - * - * We keep a minimum size of 512 bytes for the plaintext - * of our outgoing records. - * - * br_ssl_engine_set_buffers_bidi() will compute the maximum - * fragment length for outgoing records by using the minimum - * of allocated spaces for both input and output records, - * rounded down to a standard length. - */ - if (bidi) { - size_t w; - - if (buf_len < (512 + MAX_IN_OVERHEAD - + 512 + MAX_OUT_OVERHEAD)) - { - rc->iomode = BR_IO_FAILED; - rc->err = BR_ERR_BAD_PARAM; - return; - } else if (buf_len < (16384 + MAX_IN_OVERHEAD - + 512 + MAX_OUT_OVERHEAD)) - { - w = 512 + MAX_OUT_OVERHEAD; - } else { - w = buf_len - (16384 + MAX_IN_OVERHEAD); - } - br_ssl_engine_set_buffers_bidi(rc, - buf, buf_len - w, - (unsigned char *)buf + w, w); - } else { - br_ssl_engine_set_buffers_bidi(rc, - buf, buf_len, NULL, 0); - } - } -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *rc, - void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len) -{ - rc->iomode = BR_IO_INOUT; - rc->incrypt = 0; - rc->err = BR_ERR_OK; - rc->version_in = 0; - rc->record_type_in = 0; - rc->version_out = 0; - rc->record_type_out = 0; - if (ibuf == NULL) { - if (rc->ibuf == NULL) { - br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM); - } - } else { - unsigned u; - - rc->ibuf = ibuf; - rc->ibuf_len = ibuf_len; - if (obuf == NULL) { - obuf = ibuf; - obuf_len = ibuf_len; - } - rc->obuf = obuf; - rc->obuf_len = obuf_len; - - /* - * Compute the maximum fragment length, that fits for - * both incoming and outgoing records. This length will - * be used in fragment length negotiation, so we must - * honour it both ways. Regardless, larger incoming - * records will be accepted, as long as they fit in the - * actual buffer size. - */ - for (u = 14; u >= 9; u --) { - size_t flen; - - flen = (size_t)1 << u; - if (obuf_len >= flen + MAX_OUT_OVERHEAD - && ibuf_len >= flen + MAX_IN_OVERHEAD) - { - break; - } - } - if (u == 8) { - br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM); - return; - } else if (u == 13) { - u = 12; - } - rc->max_frag_len = (size_t)1 << u; - rc->log_max_frag_len = u; - rc->peer_log_max_frag_len = 0; - } - rc->out.vtable = &br_sslrec_out_clear_vtable; - make_ready_in(rc); - make_ready_out(rc); -} - -/* - * Clear buffers in both directions. - */ -static void -engine_clearbuf(br_ssl_engine_context *rc) -{ - make_ready_in(rc); - make_ready_out(rc); -} - -/* - * Make sure the internal PRNG is initialised (but not necessarily - * seeded properly yet). - */ -static int -rng_init(br_ssl_engine_context *cc) -{ - const br_hash_class *h; - - if (cc->rng_init_done != 0) { - return 1; - } - - /* - * If using TLS-1.2, then SHA-256 or SHA-384 must be present (or - * both); we prefer SHA-256 which is faster for 32-bit systems. - * - * If using TLS-1.0 or 1.1 then SHA-1 must be present. - * - * Though HMAC_DRBG/SHA-1 is, as far as we know, as safe as - * these things can be, we still prefer the SHA-2 functions over - * SHA-1, if only for public relations (known theoretical - * weaknesses of SHA-1 with regards to collisions are mostly - * irrelevant here, but they still make people nervous). - */ - h = br_multihash_getimpl(&cc->mhash, br_sha256_ID); - if (!h) { - h = br_multihash_getimpl(&cc->mhash, br_sha384_ID); - if (!h) { - h = br_multihash_getimpl(&cc->mhash, - br_sha1_ID); - if (!h) { - br_ssl_engine_fail(cc, BR_ERR_BAD_STATE); - return 0; - } - } - } - br_hmac_drbg_init(&cc->rng, h, NULL, 0); - cc->rng_init_done = 1; - return 1; -} - -/* see inner.h */ -int -br_ssl_engine_init_rand(br_ssl_engine_context *cc) -{ - if (!rng_init(cc)) { - return 0; - } - - /* - * We always try OS/hardware seeding once. If it works, then - * we assume proper seeding. If not, then external entropy must - * have been injected; otherwise, we report an error. - */ - if (!cc->rng_os_rand_done) { - br_prng_seeder sd; - - sd = br_prng_seeder_system(NULL); - if (sd != 0 && sd(&cc->rng.vtable)) { - cc->rng_init_done = 2; - } - cc->rng_os_rand_done = 1; - } - if (cc->rng_init_done < 2) { - br_ssl_engine_fail(cc, BR_ERR_NO_RANDOM); - return 0; - } - return 1; -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_inject_entropy(br_ssl_engine_context *cc, - const void *data, size_t len) -{ - /* - * Externally provided entropy is assumed to be "good enough" - * (we cannot really test its quality) so if the RNG structure - * could be initialised at all, then we marked the RNG as - * "properly seeded". - */ - if (!rng_init(cc)) { - return; - } - br_hmac_drbg_update(&cc->rng, data, len); - cc->rng_init_done = 2; -} - -/* - * We define a few internal functions that implement the low-level engine - * API for I/O; the external API (br_ssl_engine_sendapp_buf() and similar - * functions) is built upon these function, with special processing for - * records which are not of type "application data". - * - * recvrec_buf, recvrec_ack receives bytes from transport medium - * sendrec_buf, sendrec_ack send bytes to transport medium - * recvpld_buf, recvpld_ack receives payload data from engine - * sendpld_buf, sendpld_ack send payload data to engine - */ - -static unsigned char * -recvrec_buf(const br_ssl_engine_context *rc, size_t *len) -{ - if (rc->shutdown_recv) { - *len = 0; - return NULL; - } - - /* - * Bytes from the transport can be injected only if the mode is - * compatible (in or in/out), and ixa == ixb; ixc then contains - * the number of bytes that are still expected (but it may - * exceed our buffer size). - * - * We cannot get "stuck" here (buffer is full, but still more - * data is expected) because oversized records are detected when - * their header is processed. - */ - switch (rc->iomode) { - case BR_IO_IN: - case BR_IO_INOUT: - if (rc->ixa == rc->ixb) { - size_t z; - - z = rc->ixc; - if (z > rc->ibuf_len - rc->ixa) { - z = rc->ibuf_len - rc->ixa; - } - *len = z; - return rc->ibuf + rc->ixa; - } - break; - } - *len = 0; - return NULL; -} - -static void -recvrec_ack(br_ssl_engine_context *rc, size_t len) -{ - unsigned char *pbuf; - size_t pbuf_len; - - /* - * Adjust state if necessary (for a shared input/output buffer): - * we got some incoming bytes, so we cannot (temporarily) handle - * outgoing data. - */ - if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) { - rc->iomode = BR_IO_IN; - } - - /* - * Adjust data pointers. - */ - rc->ixb = (rc->ixa += len); - rc->ixc -= len; - - /* - * If we are receiving a header and did not fully obtained it - * yet, then just wait for the next bytes. - */ - if (rc->ixa < 5) { - return; - } - - /* - * If we just obtained a full header, process it. - */ - if (rc->ixa == 5) { - unsigned version; - unsigned rlen; - - /* - * Get record type and version. We support only versions - * 3.x (if the version major number does not match, then - * we suppose that the record format is too alien for us - * to process it). - * - * Note: right now, we reject clients that try to send - * a ClientHello in a format compatible with SSL-2.0. It - * is unclear whether this will ever be supported; and - * if we want to support it, then this might be done in - * in the server-specific code, not here. - */ - rc->record_type_in = rc->ibuf[0]; - version = br_dec16be(rc->ibuf + 1); - if ((version >> 8) != 3) { - br_ssl_engine_fail(rc, BR_ERR_UNSUPPORTED_VERSION); - return; - } - - /* - * We ensure that successive records have the same - * version. The handshake code must check and adjust the - * variables when necessary to accommodate the protocol - * negotiation details. - */ - if (rc->version_in != 0 && rc->version_in != version) { - br_ssl_engine_fail(rc, BR_ERR_BAD_VERSION); - return; - } - rc->version_in = version; - - /* - * Decode record length. We must check that the length - * is valid (relatively to the current encryption mode) - * and also (if encryption is active) that the record - * will fit in our buffer. - * - * When no encryption is active, we can process records - * by chunks, and thus accept any record up to the - * maximum allowed plaintext length (16384 bytes). - */ - rlen = br_dec16be(rc->ibuf + 3); - if (rc->incrypt) { - if (!rc->in.vtable->check_length( - &rc->in.vtable, rlen)) - { - br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH); - return; - } - if (rlen > (rc->ibuf_len - 5)) { - br_ssl_engine_fail(rc, BR_ERR_TOO_LARGE); - return; - } - } else { - if (rlen > 16384) { - br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH); - return; - } - } - - /* - * If the record is completely empty then we must switch - * to a new record. Note that, in that case, we - * completely ignore the record type, which is fitting - * since we received no actual data of that type. - * - * A completely empty record is technically allowed as - * long as encryption/MAC is not active, i.e. before - * completion of the first handshake. It it still weird; - * it might conceptually be useful as a heartbeat or - * keep-alive mechanism while some lengthy operation is - * going on, e.g. interaction with a human user. - */ - if (rlen == 0) { - make_ready_in(rc); - } else { - rc->ixa = rc->ixb = 5; - rc->ixc = rlen; - } - return; - } - - /* - * If there is no active encryption, then the data can be read - * right away. Note that we do not receive bytes from the - * transport medium when we still have payload bytes to be - * acknowledged. - */ - if (!rc->incrypt) { - rc->ixa = 5; - return; - } - - /* - * Since encryption is active, we must wait for a full record - * before processing it. - */ - if (rc->ixc != 0) { - return; - } - - /* - * We got the full record. Decrypt it. - */ - pbuf_len = rc->ixa - 5; - pbuf = rc->in.vtable->decrypt(&rc->in.vtable, - rc->record_type_in, rc->version_in, rc->ibuf + 5, &pbuf_len); - if (pbuf == 0) { - br_ssl_engine_fail(rc, BR_ERR_BAD_MAC); - return; - } - rc->ixa = (size_t)(pbuf - rc->ibuf); - rc->ixb = rc->ixa + pbuf_len; - - /* - * Decryption may have yielded an empty record, in which case - * we get back to "ready" state immediately. - */ - if (rc->ixa == rc->ixb) { - make_ready_in(rc); - } -} - -/* see inner.h */ -int -br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc) -{ - switch (rc->iomode) { - case BR_IO_IN: - case BR_IO_INOUT: - return rc->ixc == 0 || rc->ixa < 5; - default: - return 1; - } -} - -static unsigned char * -recvpld_buf(const br_ssl_engine_context *rc, size_t *len) -{ - /* - * There is payload data to be read only if the mode is - * compatible, and ixa != ixb. - */ - switch (rc->iomode) { - case BR_IO_IN: - case BR_IO_INOUT: - *len = rc->ixb - rc->ixa; - return (*len == 0) ? NULL : (rc->ibuf + rc->ixa); - default: - *len = 0; - return NULL; - } -} - -static void -recvpld_ack(br_ssl_engine_context *rc, size_t len) -{ - rc->ixa += len; - - /* - * If we read all the available data, then we either expect - * the remainder of the current record (if the current record - * was not finished; this may happen when encryption is not - * active), or go to "ready" state. - */ - if (rc->ixa == rc->ixb) { - if (rc->ixc == 0) { - make_ready_in(rc); - } else { - rc->ixa = rc->ixb = 5; - } - } -} - -static unsigned char * -sendpld_buf(const br_ssl_engine_context *rc, size_t *len) -{ - /* - * Payload data can be injected only if the current mode is - * compatible, and oxa != oxb. - */ - switch (rc->iomode) { - case BR_IO_OUT: - case BR_IO_INOUT: - *len = rc->oxb - rc->oxa; - return (*len == 0) ? NULL : (rc->obuf + rc->oxa); - default: - *len = 0; - return NULL; - } -} - -/* - * If some payload bytes have been accumulated, then wrap them into - * an outgoing record. Otherwise, this function does nothing, unless - * 'force' is non-zero, in which case an empty record is assembled. - * - * The caller must take care not to invoke this function if the engine - * is not currently ready to receive payload bytes to send. - */ -static void -sendpld_flush(br_ssl_engine_context *rc, int force) -{ - size_t xlen; - unsigned char *buf; - - if (rc->oxa == rc->oxb) { - return; - } - xlen = rc->oxa - rc->oxc; - if (xlen == 0 && !force) { - return; - } - buf = rc->out.vtable->encrypt(&rc->out.vtable, - rc->record_type_out, rc->version_out, - rc->obuf + rc->oxc, &xlen); - rc->oxb = rc->oxa = (size_t)(buf - rc->obuf); - rc->oxc = rc->oxa + xlen; -} - -static void -sendpld_ack(br_ssl_engine_context *rc, size_t len) -{ - /* - * If using a shared buffer, then we may have to modify the - * current mode. - */ - if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) { - rc->iomode = BR_IO_OUT; - } - rc->oxa += len; - if (rc->oxa >= rc->oxb) { - /* - * Set oxb to one more than oxa so that sendpld_flush() - * does not mistakingly believe that a record is - * already prepared and being sent. - */ - rc->oxb = rc->oxa + 1; - sendpld_flush(rc, 0); - } -} - -static unsigned char * -sendrec_buf(const br_ssl_engine_context *rc, size_t *len) -{ - /* - * When still gathering payload bytes, oxc points to the start - * of the record data, so oxc <= oxa. However, when a full - * record has been completed, oxc points to the end of the record, - * so oxc > oxa. - */ - switch (rc->iomode) { - case BR_IO_OUT: - case BR_IO_INOUT: - if (rc->oxc > rc->oxa) { - *len = rc->oxc - rc->oxa; - return rc->obuf + rc->oxa; - } - break; - } - *len = 0; - return NULL; -} - -static void -sendrec_ack(br_ssl_engine_context *rc, size_t len) -{ - rc->oxb = (rc->oxa += len); - if (rc->oxa == rc->oxc) { - make_ready_out(rc); - } -} - -/* - * Test whether there is some buffered outgoing record that still must - * sent. - */ -static inline int -has_rec_tosend(const br_ssl_engine_context *rc) -{ - return rc->oxa == rc->oxb && rc->oxa != rc->oxc; -} - -/* - * The "no encryption" mode has no overhead. It limits the payload size - * to the maximum size allowed by the standard (16384 bytes); the caller - * is responsible for possibly enforcing a smaller fragment length. - */ -static void -clear_max_plaintext(const br_sslrec_out_clear_context *cc, - size_t *start, size_t *end) -{ - size_t len; - - (void)cc; - len = *end - *start; - if (len > 16384) { - *end = *start + 16384; - } -} - -/* - * In "no encryption" mode, encryption is trivial (a no-operation) so - * we just have to encode the header. - */ -static unsigned char * -clear_encrypt(br_sslrec_out_clear_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf; - - (void)cc; - buf = (unsigned char *)data - 5; - buf[0] = record_type; - br_enc16be(buf + 1, version); - br_enc16be(buf + 3, *data_len); - *data_len += 5; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_out_class br_sslrec_out_clear_vtable = { - sizeof(br_sslrec_out_clear_context), - (void (*)(const br_sslrec_out_class *const *, size_t *, size_t *)) - &clear_max_plaintext, - (unsigned char *(*)(const br_sslrec_out_class **, - int, unsigned, void *, size_t *)) - &clear_encrypt -}; - -/* ==================================================================== */ -/* - * In this part of the file, we handle the various record types, and - * communications with the handshake processor. - */ - -/* - * IMPLEMENTATION NOTES - * ==================== - * - * The handshake processor is written in T0 and runs as a coroutine. - * It receives the contents of all records except application data, and - * is responsible for producing the contents of all records except - * application data. - * - * A state flag is maintained, which specifies whether application data - * is acceptable or not. When it is set: - * - * -- Application data can be injected as payload data (provided that - * the output buffer is ready for that). - * - * -- Incoming application data records are accepted, and yield data - * that the caller may retrieve. - * - * When the flag is cleared, application data is not accepted from the - * application, and incoming application data records trigger an error. - * - * - * Records of type handshake, alert or change-cipher-spec are handled - * by the handshake processor. The handshake processor is written in T0 - * and runs as a coroutine; it gets invoked whenever one of the following - * situations is reached: - * - * -- An incoming record has type handshake, alert or change-cipher-spec, - * and yields data that can be read (zero-length records are thus - * ignored). - * - * -- An outgoing record has just finished being sent, and the "application - * data" flag is cleared. - * - * -- The caller wishes to perform a close (call to br_ssl_engine_close()). - * - * -- The caller wishes to perform a renegotiation (call to - * br_ssl_engine_renegotiate()). - * - * Whenever the handshake processor is entered, access to the payload - * buffers is provided, along with some information about explicit - * closures or renegotiations. - */ - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_suites(br_ssl_engine_context *cc, - const uint16_t *suites, size_t suites_num) -{ - if ((suites_num * sizeof *suites) > sizeof cc->suites_buf) { - br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM); - return; - } - memcpy(cc->suites_buf, suites, suites_num * sizeof *suites); - cc->suites_num = suites_num; -} - -/* - * Give control to handshake processor. 'action' is 1 for a close, - * 2 for a renegotiation, or 0 for a jump due to I/O completion. - */ -static void -jump_handshake(br_ssl_engine_context *cc, int action) -{ - /* - * We use a loop because the handshake processor actions may - * allow for more actions; namely, if the processor reads all - * input data, then it may allow for output data to be produced, - * in case of a shared in/out buffer. - */ - for (;;) { - size_t hlen_in, hlen_out; - - /* - * Get input buffer. We do not want to provide - * application data to the handshake processor (we could - * get called with an explicit close or renegotiation - * while there is application data ready to be read). - */ - cc->hbuf_in = recvpld_buf(cc, &hlen_in); - if (cc->hbuf_in != NULL - && cc->record_type_in == BR_SSL_APPLICATION_DATA) - { - hlen_in = 0; - } - - /* - * Get output buffer. The handshake processor never - * leaves an unfinished outgoing record, so if there is - * buffered output, then it MUST be some application - * data, so the processor cannot write to it. - */ - cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &hlen_out); - if (cc->hbuf_out != NULL && br_ssl_engine_has_pld_to_send(cc)) { - hlen_out = 0; - } - - /* - * Note: hlen_in and hlen_out can be both non-zero only if - * the input and output buffers are disjoint. Thus, we can - * offer both buffers to the handshake code. - */ - - cc->hlen_in = hlen_in; - cc->hlen_out = hlen_out; - cc->action = action; - cc->hsrun(&cc->cpu); - if (br_ssl_engine_closed(cc)) { - return; - } - if (cc->hbuf_out != cc->saved_hbuf_out) { - sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out); - } - if (hlen_in != cc->hlen_in) { - recvpld_ack(cc, hlen_in - cc->hlen_in); - if (cc->hlen_in == 0) { - /* - * We read all data bytes, which may have - * released the output buffer in case it - * is shared with the input buffer, and - * the handshake code might be waiting for - * that. - */ - action = 0; - continue; - } - } - break; - } -} - -/* see inner.h */ -void -br_ssl_engine_flush_record(br_ssl_engine_context *cc) -{ - if (cc->hbuf_out != cc->saved_hbuf_out) { - sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out); - } - if (br_ssl_engine_has_pld_to_send(cc)) { - sendpld_flush(cc, 0); - } - cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &cc->hlen_out); -} - -/* see bearssl_ssl.h */ -unsigned char * -br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len) -{ - if (!(cc->application_data & 1)) { - *len = 0; - return NULL; - } - return sendpld_buf(cc, len); -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len) -{ - sendpld_ack(cc, len); -} - -/* see bearssl_ssl.h */ -unsigned char * -br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len) -{ - if (!(cc->application_data & 1) - || cc->record_type_in != BR_SSL_APPLICATION_DATA) - { - *len = 0; - return NULL; - } - return recvpld_buf(cc, len); -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len) -{ - recvpld_ack(cc, len); -} - -/* see bearssl_ssl.h */ -unsigned char * -br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, size_t *len) -{ - return sendrec_buf(cc, len); -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len) -{ - sendrec_ack(cc, len); - if (len != 0 && !has_rec_tosend(cc) - && (cc->record_type_out != BR_SSL_APPLICATION_DATA - || (cc->application_data & 1) == 0)) - { - jump_handshake(cc, 0); - } -} - -/* see bearssl_ssl.h */ -unsigned char * -br_ssl_engine_recvrec_buf(const br_ssl_engine_context *cc, size_t *len) -{ - return recvrec_buf(cc, len); -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len) -{ - unsigned char *buf; - - recvrec_ack(cc, len); - if (br_ssl_engine_closed(cc)) { - return; - } - - /* - * We just received some bytes from the peer. This may have - * yielded some payload bytes, in which case we must process - * them according to the record type. - */ - buf = recvpld_buf(cc, &len); - if (buf != NULL) { - switch (cc->record_type_in) { - case BR_SSL_CHANGE_CIPHER_SPEC: - case BR_SSL_ALERT: - case BR_SSL_HANDSHAKE: - jump_handshake(cc, 0); - break; - case BR_SSL_APPLICATION_DATA: - if (cc->application_data == 1) { - break; - } - - /* - * If we are currently closing, and waiting for - * a close_notify from the peer, then incoming - * application data should be discarded. - */ - if (cc->application_data == 2) { - recvpld_ack(cc, len); - break; - } - - /* Fall through */ - default: - br_ssl_engine_fail(cc, BR_ERR_UNEXPECTED); - break; - } - } -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_close(br_ssl_engine_context *cc) -{ - if (!br_ssl_engine_closed(cc)) { - jump_handshake(cc, 1); - } -} - -/* see bearssl_ssl.h */ -int -br_ssl_engine_renegotiate(br_ssl_engine_context *cc) -{ - size_t len; - - if (br_ssl_engine_closed(cc) || cc->reneg == 1 - || (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0 - || br_ssl_engine_recvapp_buf(cc, &len) != NULL) - { - return 0; - } - jump_handshake(cc, 2); - return 1; -} - -/* see bearssl.h */ -unsigned -br_ssl_engine_current_state(const br_ssl_engine_context *cc) -{ - unsigned s; - size_t len; - - if (br_ssl_engine_closed(cc)) { - return BR_SSL_CLOSED; - } - - s = 0; - if (br_ssl_engine_sendrec_buf(cc, &len) != NULL) { - s |= BR_SSL_SENDREC; - } - if (br_ssl_engine_recvrec_buf(cc, &len) != NULL) { - s |= BR_SSL_RECVREC; - } - if (br_ssl_engine_sendapp_buf(cc, &len) != NULL) { - s |= BR_SSL_SENDAPP; - } - if (br_ssl_engine_recvapp_buf(cc, &len) != NULL) { - s |= BR_SSL_RECVAPP; - } - return s; -} - -/* see bearssl_ssl.h */ -void -br_ssl_engine_flush(br_ssl_engine_context *cc, int force) -{ - if (!br_ssl_engine_closed(cc) && (cc->application_data & 1) != 0) { - sendpld_flush(cc, force); - } -} - -/* see inner.h */ -void -br_ssl_engine_hs_reset(br_ssl_engine_context *cc, - void (*hsinit)(void *), void (*hsrun)(void *)) -{ - engine_clearbuf(cc); - cc->cpu.dp = cc->dp_stack; - cc->cpu.rp = cc->rp_stack; - hsinit(&cc->cpu); - cc->hsrun = hsrun; - cc->shutdown_recv = 0; - cc->application_data = 0; - cc->alert = 0; - jump_handshake(cc, 0); -} - -/* see inner.h */ -br_tls_prf_impl -br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id) -{ - if (cc->session.version >= BR_TLS12) { - if (prf_id == br_sha384_ID) { - return cc->prf_sha384; - } else { - return cc->prf_sha256; - } - } else { - return cc->prf10; - } -} - -/* see inner.h */ -void -br_ssl_engine_compute_master(br_ssl_engine_context *cc, - int prf_id, const void *pms, size_t pms_len) -{ - br_tls_prf_impl iprf; - br_tls_prf_seed_chunk seed[2] = { - { cc->client_random, sizeof cc->client_random }, - { cc->server_random, sizeof cc->server_random } - }; - - iprf = br_ssl_engine_get_PRF(cc, prf_id); - iprf(cc->session.master_secret, sizeof cc->session.master_secret, - pms, pms_len, "master secret", 2, seed); -} - -/* - * Compute key block. - */ -static void -compute_key_block(br_ssl_engine_context *cc, int prf_id, - size_t half_len, unsigned char *kb) -{ - br_tls_prf_impl iprf; - br_tls_prf_seed_chunk seed[2] = { - { cc->server_random, sizeof cc->server_random }, - { cc->client_random, sizeof cc->client_random } - }; - - iprf = br_ssl_engine_get_PRF(cc, prf_id); - iprf(kb, half_len << 1, - cc->session.master_secret, sizeof cc->session.master_secret, - "key expansion", 2, seed); -} - -/* see inner.h */ -void -br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc, - int is_client, int prf_id, int mac_id, - const br_block_cbcdec_class *bc_impl, size_t cipher_key_len) -{ - unsigned char kb[192]; - unsigned char *cipher_key, *mac_key, *iv; - const br_hash_class *imh; - size_t mac_key_len, mac_out_len, iv_len; - - imh = br_ssl_engine_get_hash(cc, mac_id); - mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; - mac_key_len = mac_out_len; - - /* - * TLS 1.1+ uses per-record explicit IV, so no IV to generate here. - */ - if (cc->session.version >= BR_TLS11) { - iv_len = 0; - } else { - iv_len = bc_impl->block_size; - } - compute_key_block(cc, prf_id, - mac_key_len + cipher_key_len + iv_len, kb); - if (is_client) { - mac_key = &kb[mac_key_len]; - cipher_key = &kb[(mac_key_len << 1) + cipher_key_len]; - iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len]; - } else { - mac_key = &kb[0]; - cipher_key = &kb[mac_key_len << 1]; - iv = &kb[(mac_key_len + cipher_key_len) << 1]; - } - if (iv_len == 0) { - iv = NULL; - } - cc->icbc_in->init(&cc->in.cbc.vtable, - bc_impl, cipher_key, cipher_key_len, - imh, mac_key, mac_key_len, mac_out_len, iv); - cc->incrypt = 1; -} - -/* see inner.h */ -void -br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc, - int is_client, int prf_id, int mac_id, - const br_block_cbcenc_class *bc_impl, size_t cipher_key_len) -{ - unsigned char kb[192]; - unsigned char *cipher_key, *mac_key, *iv; - const br_hash_class *imh; - size_t mac_key_len, mac_out_len, iv_len; - - imh = br_ssl_engine_get_hash(cc, mac_id); - mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; - mac_key_len = mac_out_len; - - /* - * TLS 1.1+ uses per-record explicit IV, so no IV to generate here. - */ - if (cc->session.version >= BR_TLS11) { - iv_len = 0; - } else { - iv_len = bc_impl->block_size; - } - compute_key_block(cc, prf_id, - mac_key_len + cipher_key_len + iv_len, kb); - if (is_client) { - mac_key = &kb[0]; - cipher_key = &kb[mac_key_len << 1]; - iv = &kb[(mac_key_len + cipher_key_len) << 1]; - } else { - mac_key = &kb[mac_key_len]; - cipher_key = &kb[(mac_key_len << 1) + cipher_key_len]; - iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len]; - } - if (iv_len == 0) { - iv = NULL; - } - cc->icbc_out->init(&cc->out.cbc.vtable, - bc_impl, cipher_key, cipher_key_len, - imh, mac_key, mac_key_len, mac_out_len, iv); -} - -/* see inner.h */ -void -br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctr_class *bc_impl, size_t cipher_key_len) -{ - unsigned char kb[72]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, cipher_key_len + 4, kb); - if (is_client) { - cipher_key = &kb[cipher_key_len]; - iv = &kb[(cipher_key_len << 1) + 4]; - } else { - cipher_key = &kb[0]; - iv = &kb[cipher_key_len << 1]; - } - cc->igcm_in->init(&cc->in.gcm.vtable.in, - bc_impl, cipher_key, cipher_key_len, cc->ighash, iv); - cc->incrypt = 1; -} - -/* see inner.h */ -void -br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctr_class *bc_impl, size_t cipher_key_len) -{ - unsigned char kb[72]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, cipher_key_len + 4, kb); - if (is_client) { - cipher_key = &kb[0]; - iv = &kb[cipher_key_len << 1]; - } else { - cipher_key = &kb[cipher_key_len]; - iv = &kb[(cipher_key_len << 1) + 4]; - } - cc->igcm_out->init(&cc->out.gcm.vtable.out, - bc_impl, cipher_key, cipher_key_len, cc->ighash, iv); -} - -/* see inner.h */ -void -br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc, - int is_client, int prf_id) -{ - unsigned char kb[88]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, 44, kb); - if (is_client) { - cipher_key = &kb[32]; - iv = &kb[76]; - } else { - cipher_key = &kb[0]; - iv = &kb[64]; - } - cc->ichapol_in->init(&cc->in.chapol.vtable.in, - cc->ichacha, cc->ipoly, cipher_key, iv); - cc->incrypt = 1; -} - -/* see inner.h */ -void -br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc, - int is_client, int prf_id) -{ - unsigned char kb[88]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, 44, kb); - if (is_client) { - cipher_key = &kb[0]; - iv = &kb[64]; - } else { - cipher_key = &kb[32]; - iv = &kb[76]; - } - cc->ichapol_out->init(&cc->out.chapol.vtable.out, - cc->ichacha, cc->ipoly, cipher_key, iv); -} - -/* see inner.h */ -void -br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctrcbc_class *bc_impl, - size_t cipher_key_len, size_t tag_len) -{ - unsigned char kb[72]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, cipher_key_len + 4, kb); - if (is_client) { - cipher_key = &kb[cipher_key_len]; - iv = &kb[(cipher_key_len << 1) + 4]; - } else { - cipher_key = &kb[0]; - iv = &kb[cipher_key_len << 1]; - } - cc->iccm_in->init(&cc->in.ccm.vtable.in, - bc_impl, cipher_key, cipher_key_len, iv, tag_len); - cc->incrypt = 1; -} - -/* see inner.h */ -void -br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc, - int is_client, int prf_id, - const br_block_ctrcbc_class *bc_impl, - size_t cipher_key_len, size_t tag_len) -{ - unsigned char kb[72]; - unsigned char *cipher_key, *iv; - - compute_key_block(cc, prf_id, cipher_key_len + 4, kb); - if (is_client) { - cipher_key = &kb[0]; - iv = &kb[cipher_key_len << 1]; - } else { - cipher_key = &kb[cipher_key_len]; - iv = &kb[(cipher_key_len << 1) + 4]; - } - cc->iccm_out->init(&cc->out.ccm.vtable.out, - bc_impl, cipher_key, cipher_key_len, iv, tag_len); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_aescbc.c b/src/tls/bearssl/ssl_engine_default_aescbc.c deleted file mode 100644 index 91bd3d812..000000000 --- a/src/tls/bearssl/ssl_engine_default_aescbc.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc) -{ -#if BR_AES_X86NI || BR_POWER8 - const br_block_cbcenc_class *ienc; - const br_block_cbcdec_class *idec; -#endif - - br_ssl_engine_set_cbc(cc, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); -#if BR_AES_X86NI - ienc = br_aes_x86ni_cbcenc_get_vtable(); - idec = br_aes_x86ni_cbcdec_get_vtable(); - if (ienc != NULL && idec != NULL) { - br_ssl_engine_set_aes_cbc(cc, ienc, idec); - return; - } -#endif -#if BR_POWER8 - ienc = br_aes_pwr8_cbcenc_get_vtable(); - idec = br_aes_pwr8_cbcdec_get_vtable(); - if (ienc != NULL && idec != NULL) { - br_ssl_engine_set_aes_cbc(cc, ienc, idec); - return; - } -#endif -#if BR_64 - br_ssl_engine_set_aes_cbc(cc, - &br_aes_ct64_cbcenc_vtable, - &br_aes_ct64_cbcdec_vtable); -#else - br_ssl_engine_set_aes_cbc(cc, - &br_aes_ct_cbcenc_vtable, - &br_aes_ct_cbcdec_vtable); -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_aesccm.c b/src/tls/bearssl/ssl_engine_default_aesccm.c deleted file mode 100644 index dcc12d668..000000000 --- a/src/tls/bearssl/ssl_engine_default_aesccm.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc) -{ -#if BR_AES_X86NI || BR_POWER8 - const br_block_ctrcbc_class *ictrcbc; -#endif - - br_ssl_engine_set_ccm(cc, - &br_sslrec_in_ccm_vtable, - &br_sslrec_out_ccm_vtable); -#if BR_AES_X86NI - ictrcbc = br_aes_x86ni_ctrcbc_get_vtable(); - if (ictrcbc != NULL) { - br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc); - } else { -#if BR_64 - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); -#else - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); -#endif - } -#elif BR_POWER8 - ictrcbc = br_aes_pwr8_ctrcbc_get_vtable(); - if (ictrcbc != NULL) { - br_ssl_engine_set_aes_ctrcbc(cc, ictrcbc); - } else { -#if BR_64 - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); -#else - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); -#endif - } -#else -#if BR_64 - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct64_ctrcbc_vtable); -#else - br_ssl_engine_set_aes_ctrcbc(cc, &br_aes_ct_ctrcbc_vtable); -#endif -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_aesgcm.c b/src/tls/bearssl/ssl_engine_default_aesgcm.c deleted file mode 100644 index 145a01c18..000000000 --- a/src/tls/bearssl/ssl_engine_default_aesgcm.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc) -{ -#if BR_AES_X86NI || BR_POWER8 - const br_block_ctr_class *ictr; - br_ghash ighash; -#endif - - br_ssl_engine_set_gcm(cc, - &br_sslrec_in_gcm_vtable, - &br_sslrec_out_gcm_vtable); -#if BR_AES_X86NI - ictr = br_aes_x86ni_ctr_get_vtable(); - if (ictr != NULL) { - br_ssl_engine_set_aes_ctr(cc, ictr); - } else { -#if BR_64 - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); -#else - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); -#endif - } -#elif BR_POWER8 - ictr = br_aes_pwr8_ctr_get_vtable(); - if (ictr != NULL) { - br_ssl_engine_set_aes_ctr(cc, ictr); - } else { -#if BR_64 - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); -#else - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); -#endif - } -#else -#if BR_64 - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable); -#else - br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable); -#endif -#endif -#if BR_AES_X86NI - ighash = br_ghash_pclmul_get(); - if (ighash != 0) { - br_ssl_engine_set_ghash(cc, ighash); - return; - } -#endif -#if BR_POWER8 - ighash = br_ghash_pwr8_get(); - if (ighash != 0) { - br_ssl_engine_set_ghash(cc, ighash); - return; - } -#endif -#if BR_LOMUL - br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32); -#elif BR_64 - br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64); -#else - br_ssl_engine_set_ghash(cc, &br_ghash_ctmul); -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_chapol.c b/src/tls/bearssl/ssl_engine_default_chapol.c deleted file mode 100644 index ae1007228..000000000 --- a/src/tls/bearssl/ssl_engine_default_chapol.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc) -{ -#if BR_INT128 || BR_UMUL128 - br_poly1305_run bp; -#endif -#if BR_SSE2 - br_chacha20_run bc; -#endif - - br_ssl_engine_set_chapol(cc, - &br_sslrec_in_chapol_vtable, - &br_sslrec_out_chapol_vtable); -#if BR_SSE2 - bc = br_chacha20_sse2_get(); - if (bc) { - br_ssl_engine_set_chacha20(cc, bc); - } else { -#endif - br_ssl_engine_set_chacha20(cc, &br_chacha20_ct_run); -#if BR_SSE2 - } -#endif -#if BR_INT128 || BR_UMUL128 - bp = br_poly1305_ctmulq_get(); - if (bp) { - br_ssl_engine_set_poly1305(cc, bp); - } else { -#endif -#if BR_LOMUL - br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run); -#else - br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run); -#endif -#if BR_INT128 || BR_UMUL128 - } -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_descbc.c b/src/tls/bearssl/ssl_engine_default_descbc.c deleted file mode 100644 index 81d486715..000000000 --- a/src/tls/bearssl/ssl_engine_default_descbc.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc) -{ - br_ssl_engine_set_cbc(cc, - &br_sslrec_in_cbc_vtable, - &br_sslrec_out_cbc_vtable); - br_ssl_engine_set_des_cbc(cc, - &br_des_ct_cbcenc_vtable, - &br_des_ct_cbcdec_vtable); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_ec.c b/src/tls/bearssl/ssl_engine_default_ec.c deleted file mode 100644 index 687b61481..000000000 --- a/src/tls/bearssl/ssl_engine_default_ec.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_ec(br_ssl_engine_context *cc) -{ -#if BR_LOMUL - br_ssl_engine_set_ec(cc, &br_ec_all_m15); -#else - br_ssl_engine_set_ec(cc, &br_ec_all_m31); -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_ecdsa.c b/src/tls/bearssl/ssl_engine_default_ecdsa.c deleted file mode 100644 index 194bce0fe..000000000 --- a/src/tls/bearssl/ssl_engine_default_ecdsa.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc) -{ -#if BR_LOMUL - br_ssl_engine_set_ec(cc, &br_ec_all_m15); - br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1); -#else - br_ssl_engine_set_ec(cc, &br_ec_all_m31); - br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1); -#endif -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_engine_default_rsavrfy.c b/src/tls/bearssl/ssl_engine_default_rsavrfy.c deleted file mode 100644 index b94a3fc6c..000000000 --- a/src/tls/bearssl/ssl_engine_default_rsavrfy.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc) -{ - br_ssl_engine_set_rsavrfy(cc, br_rsa_pkcs1_vrfy_get_default()); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_hashes.c b/src/tls/bearssl/ssl_hashes.c deleted file mode 100644 index 06d00a4fa..000000000 --- a/src/tls/bearssl/ssl_hashes.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see inner.h */ -int -br_ssl_choose_hash(unsigned bf) -{ - static const unsigned char pref[] = { - br_sha256_ID, br_sha384_ID, br_sha512_ID, - br_sha224_ID, br_sha1_ID - }; - size_t u; - - for (u = 0; u < sizeof pref; u ++) { - int x; - - x = pref[u]; - if ((bf >> x) & 1) { - return x; - } - } - return 0; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_hs_client.c b/src/tls/bearssl/ssl_hs_client.c deleted file mode 100644 index 716582067..000000000 --- a/src/tls/bearssl/ssl_hs_client.c +++ /dev/null @@ -1,1920 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_ssl_hs_client_init_main(void *t0ctx); - -void br_ssl_hs_client_run(void *t0ctx); - - - -#include -#include - -#include "inner.h" - -/* - * This macro evaluates to a pointer to the current engine context. - */ -#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) - - - - - -/* - * This macro evaluates to a pointer to the client context, under that - * specific name. It must be noted that since the engine context is the - * first field of the br_ssl_client_context structure ('eng'), then - * pointers values of both types are interchangeable, modulo an - * appropriate cast. This also means that "addresses" computed as offsets - * within the structure work for both kinds of context. - */ -#define CTX ((br_ssl_client_context *)ENG) - -/* - * Generate the pre-master secret for RSA key exchange, and encrypt it - * with the server's public key. Returned value is either the encrypted - * data length (in bytes), or -x on error, with 'x' being an error code. - * - * This code assumes that the public key has been already verified (it - * was properly obtained by the X.509 engine, and it has the right type, - * i.e. it is of type RSA and suitable for encryption). - */ -static int -make_pms_rsa(br_ssl_client_context *ctx, int prf_id) -{ - const br_x509_class **xc; - const br_x509_pkey *pk; - const unsigned char *n; - unsigned char *pms; - size_t nlen, u; - - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - - /* - * Compute actual RSA key length, in case there are leading zeros. - */ - n = pk->key.rsa.n; - nlen = pk->key.rsa.nlen; - while (nlen > 0 && *n == 0) { - n ++; - nlen --; - } - - /* - * We need at least 59 bytes (48 bytes for pre-master secret, and - * 11 bytes for the PKCS#1 type 2 padding). Note that the X.509 - * minimal engine normally blocks RSA keys shorter than 128 bytes, - * so this is mostly for public keys provided explicitly by the - * caller. - */ - if (nlen < 59) { - return -BR_ERR_X509_WEAK_PUBLIC_KEY; - } - if (nlen > sizeof ctx->eng.pad) { - return -BR_ERR_LIMIT_EXCEEDED; - } - - /* - * Make PMS. - */ - pms = ctx->eng.pad + nlen - 48; - br_enc16be(pms, ctx->eng.version_max); - br_hmac_drbg_generate(&ctx->eng.rng, pms + 2, 46); - br_ssl_engine_compute_master(&ctx->eng, prf_id, pms, 48); - - /* - * Apply PKCS#1 type 2 padding. - */ - ctx->eng.pad[0] = 0x00; - ctx->eng.pad[1] = 0x02; - ctx->eng.pad[nlen - 49] = 0x00; - br_hmac_drbg_generate(&ctx->eng.rng, ctx->eng.pad + 2, nlen - 51); - for (u = 2; u < nlen - 49; u ++) { - while (ctx->eng.pad[u] == 0) { - br_hmac_drbg_generate(&ctx->eng.rng, - &ctx->eng.pad[u], 1); - } - } - - /* - * Compute RSA encryption. - */ - if (!ctx->irsapub(ctx->eng.pad, nlen, &pk->key.rsa)) { - return -BR_ERR_LIMIT_EXCEEDED; - } - return (int)nlen; -} - -/* - * OID for hash functions in RSA signatures. - */ -static const unsigned char *HASH_OID[] = { - BR_HASH_OID_SHA1, - BR_HASH_OID_SHA224, - BR_HASH_OID_SHA256, - BR_HASH_OID_SHA384, - BR_HASH_OID_SHA512 -}; - -/* - * Check the RSA signature on the ServerKeyExchange message. - * - * hash hash function ID (2 to 6), or 0 for MD5+SHA-1 (with RSA only) - * use_rsa non-zero for RSA signature, zero for ECDSA - * sig_len signature length (in bytes); signature value is in the pad - * - * Returned value is 0 on success, or an error code. - */ -static int -verify_SKE_sig(br_ssl_client_context *ctx, - int hash, int use_rsa, size_t sig_len) -{ - const br_x509_class **xc; - const br_x509_pkey *pk; - br_multihash_context mhc; - unsigned char hv[64], head[4]; - size_t hv_len; - - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - br_multihash_zero(&mhc); - br_multihash_copyimpl(&mhc, &ctx->eng.mhash); - br_multihash_init(&mhc); - br_multihash_update(&mhc, - ctx->eng.client_random, sizeof ctx->eng.client_random); - br_multihash_update(&mhc, - ctx->eng.server_random, sizeof ctx->eng.server_random); - head[0] = 3; - head[1] = 0; - head[2] = ctx->eng.ecdhe_curve; - head[3] = ctx->eng.ecdhe_point_len; - br_multihash_update(&mhc, head, sizeof head); - br_multihash_update(&mhc, - ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); - if (hash) { - hv_len = br_multihash_out(&mhc, hash, hv); - if (hv_len == 0) { - return BR_ERR_INVALID_ALGORITHM; - } - } else { - if (!br_multihash_out(&mhc, br_md5_ID, hv) - || !br_multihash_out(&mhc, br_sha1_ID, hv + 16)) - { - return BR_ERR_INVALID_ALGORITHM; - } - hv_len = 36; - } - if (use_rsa) { - unsigned char tmp[64]; - const unsigned char *hash_oid; - - if (hash) { - hash_oid = HASH_OID[hash - 2]; - } else { - hash_oid = NULL; - } - if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len, - hash_oid, hv_len, &pk->key.rsa, tmp) - || memcmp(tmp, hv, hv_len) != 0) - { - return BR_ERR_BAD_SIGNATURE; - } - } else { - if (!ctx->eng.iecdsa(ctx->eng.iec, hv, hv_len, &pk->key.ec, - ctx->eng.pad, sig_len)) - { - return BR_ERR_BAD_SIGNATURE; - } - } - return 0; -} - -/* - * Perform client-side ECDH (or ECDHE). The point that should be sent to - * the server is written in the pad; returned value is either the point - * length (in bytes), or -x on error, with 'x' being an error code. - * - * The point _from_ the server is taken from ecdhe_point[] if 'ecdhe' - * is non-zero, or from the X.509 engine context if 'ecdhe' is zero - * (for static ECDH). - */ -static int -make_pms_ecdh(br_ssl_client_context *ctx, unsigned ecdhe, int prf_id) -{ - int curve; - unsigned char key[66], point[133]; - const unsigned char *order, *point_src; - size_t glen, olen, point_len, xoff, xlen; - unsigned char mask; - - if (ecdhe) { - curve = ctx->eng.ecdhe_curve; - point_src = ctx->eng.ecdhe_point; - point_len = ctx->eng.ecdhe_point_len; - } else { - const br_x509_class **xc; - const br_x509_pkey *pk; - - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - curve = pk->key.ec.curve; - point_src = pk->key.ec.q; - point_len = pk->key.ec.qlen; - } - if ((ctx->eng.iec->supported_curves & ((uint32_t)1 << curve)) == 0) { - return -BR_ERR_INVALID_ALGORITHM; - } - - /* - * We need to generate our key, as a non-zero random value which - * is lower than the curve order, in a "large enough" range. We - * force top bit to 0 and bottom bit to 1, which guarantees that - * the value is in the proper range. - */ - order = ctx->eng.iec->order(curve, &olen); - mask = 0xFF; - while (mask >= order[0]) { - mask >>= 1; - } - br_hmac_drbg_generate(&ctx->eng.rng, key, olen); - key[0] &= mask; - key[olen - 1] |= 0x01; - - /* - * Compute the common ECDH point, whose X coordinate is the - * pre-master secret. - */ - ctx->eng.iec->generator(curve, &glen); - if (glen != point_len) { - return -BR_ERR_INVALID_ALGORITHM; - } - - memcpy(point, point_src, glen); - if (!ctx->eng.iec->mul(point, glen, key, olen, curve)) { - return -BR_ERR_INVALID_ALGORITHM; - } - - /* - * The pre-master secret is the X coordinate. - */ - xoff = ctx->eng.iec->xoff(curve, &xlen); - br_ssl_engine_compute_master(&ctx->eng, prf_id, point + xoff, xlen); - - ctx->eng.iec->mulgen(point, key, olen, curve); - memcpy(ctx->eng.pad, point, glen); - return (int)glen; -} - -/* - * Perform full static ECDH. This occurs only in the context of client - * authentication with certificates: the server uses an EC public key, - * the cipher suite is of type ECDH (not ECDHE), the server requested a - * client certificate and accepts static ECDH, the client has a - * certificate with an EC public key in the same curve, and accepts - * static ECDH as well. - * - * Returned value is 0 on success, -1 on error. - */ -static int -make_pms_static_ecdh(br_ssl_client_context *ctx, int prf_id) -{ - unsigned char point[133]; - size_t point_len; - const br_x509_class **xc; - const br_x509_pkey *pk; - - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - point_len = pk->key.ec.qlen; - if (point_len > sizeof point) { - return -1; - } - memcpy(point, pk->key.ec.q, point_len); - if (!(*ctx->client_auth_vtable)->do_keyx( - ctx->client_auth_vtable, point, &point_len)) - { - return -1; - } - br_ssl_engine_compute_master(&ctx->eng, - prf_id, point, point_len); - return 0; -} - -/* - * Compute the client-side signature. This is invoked only when a - * signature-based client authentication was selected. The computed - * signature is in the pad; its length (in bytes) is returned. On - * error, 0 is returned. - */ -static size_t -make_client_sign(br_ssl_client_context *ctx) -{ - size_t hv_len; - - /* - * Compute hash of handshake messages so far. This "cannot" fail - * because the list of supported hash functions provided to the - * client certificate handler was trimmed to include only the - * hash functions that the multi-hasher supports. - */ - if (ctx->hash_id) { - hv_len = br_multihash_out(&ctx->eng.mhash, - ctx->hash_id, ctx->eng.pad); - } else { - br_multihash_out(&ctx->eng.mhash, - br_md5_ID, ctx->eng.pad); - br_multihash_out(&ctx->eng.mhash, - br_sha1_ID, ctx->eng.pad + 16); - hv_len = 36; - } - return (*ctx->client_auth_vtable)->do_sign( - ctx->client_auth_vtable, ctx->hash_id, hv_len, - ctx->eng.pad, sizeof ctx->eng.pad); -} - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02, - 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03, - 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41, - 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21, - 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31, - 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11, - 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22, - 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11, - 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32, - 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43, - 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14, - 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06, - 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09, - 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28, - 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25, - 0x04, 0x00, 0x00 -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, - 0x00, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x01, 0x01, 0x08, - 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00, - 0x01, 0x02, 0x09, 0x00, 0x00, 0x25, 0x25, 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_CIPHER_SUITE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_COMPRESSION), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_HELLO_DONE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_SNI), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_BAD_VERSION), - 0x00, 0x00, 0x01, T0_INT1(BR_ERR_EXTRA_EXTENSION), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK), - 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_RESUME_MISMATCH), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_UNSUPPORTED_VERSION), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_client_context, auth_type)), 0x00, 0x00, - 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, client_random)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_curve)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hash_id)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_client_context, hashes)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_client_context, min_clienthello_len)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00, - 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), 0x00, 0x00, - 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)), - 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)), - 0x00, 0x00, 0x09, 0x26, 0x58, 0x06, 0x02, 0x68, 0x28, 0x00, 0x00, 0x06, - 0x08, 0x2C, 0x0E, 0x05, 0x02, 0x71, 0x28, 0x04, 0x01, 0x3C, 0x00, 0x00, - 0x01, 0x01, 0x00, 0x01, 0x03, 0x00, 0x99, 0x26, 0x5E, 0x44, 0x9D, 0x26, - 0x05, 0x04, 0x60, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0E, 0x06, 0x02, 0x9D, - 0x00, 0x5E, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x68, 0x28, 0x00, 0x00, 0x26, - 0x89, 0x44, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x44, 0x79, 0x2C, 0xAB, 0x1C, - 0x84, 0x01, 0x0C, 0x31, 0x00, 0x00, 0x26, 0x1F, 0x01, 0x08, 0x0B, 0x44, - 0x5C, 0x1F, 0x08, 0x00, 0x01, 0x03, 0x00, 0x77, 0x2E, 0x02, 0x00, 0x36, - 0x17, 0x01, 0x01, 0x0B, 0x77, 0x3E, 0x29, 0x1A, 0x36, 0x06, 0x07, 0x02, - 0x00, 0xCF, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xC5, 0x02, 0x00, 0x26, - 0x1A, 0x17, 0x06, 0x02, 0x6F, 0x28, 0xCF, 0x04, 0x76, 0x01, 0x01, 0x00, - 0x77, 0x3E, 0x01, 0x16, 0x87, 0x3E, 0x01, 0x00, 0x8A, 0x3C, 0x34, 0xD5, - 0x29, 0xB4, 0x06, 0x09, 0x01, 0x7F, 0xAF, 0x01, 0x7F, 0xD2, 0x04, 0x80, - 0x53, 0xB1, 0x79, 0x2C, 0xA1, 0x01, T0_INT1(BR_KEYTYPE_SIGN), 0x17, - 0x06, 0x01, 0xB5, 0xB8, 0x26, 0x01, 0x0D, 0x0E, 0x06, 0x07, 0x25, 0xB7, - 0xB8, 0x01, 0x7F, 0x04, 0x02, 0x01, 0x00, 0x03, 0x00, 0x01, 0x0E, 0x0E, - 0x05, 0x02, 0x72, 0x28, 0x06, 0x02, 0x67, 0x28, 0x33, 0x06, 0x02, 0x72, - 0x28, 0x02, 0x00, 0x06, 0x1C, 0xD3, 0x80, 0x2E, 0x01, 0x81, 0x7F, 0x0E, - 0x06, 0x0D, 0x25, 0x01, 0x10, 0xDE, 0x01, 0x00, 0xDD, 0x79, 0x2C, 0xAB, - 0x24, 0x04, 0x04, 0xD6, 0x06, 0x01, 0xD4, 0x04, 0x01, 0xD6, 0x01, 0x7F, - 0xD2, 0x01, 0x7F, 0xAF, 0x01, 0x01, 0x77, 0x3E, 0x01, 0x17, 0x87, 0x3E, - 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x00, - 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01, - T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_KEYX), 0x04, 0x30, 0x01, 0x01, - 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01, - T0_INT1(BR_KEYTYPE_RSA | BR_KEYTYPE_SIGN), 0x04, 0x25, 0x01, 0x02, - 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01, - T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_SIGN), 0x04, 0x1A, 0x01, 0x03, - 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01, - T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x0F, 0x01, 0x04, - 0x38, 0x0E, 0x06, 0x05, 0x25, 0x01, - T0_INT1(BR_KEYTYPE_EC | BR_KEYTYPE_KEYX), 0x04, 0x04, 0x01, 0x00, - 0x44, 0x25, 0x00, 0x00, 0x82, 0x2E, 0x01, 0x0E, 0x0E, 0x06, 0x04, 0x01, - 0x00, 0x04, 0x02, 0x01, 0x05, 0x00, 0x00, 0x40, 0x06, 0x04, 0x01, 0x06, - 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x88, 0x2E, 0x26, 0x06, 0x08, 0x01, - 0x01, 0x09, 0x01, 0x11, 0x07, 0x04, 0x03, 0x25, 0x01, 0x05, 0x00, 0x01, - 0x41, 0x03, 0x00, 0x25, 0x01, 0x00, 0x43, 0x06, 0x03, 0x02, 0x00, 0x08, - 0x42, 0x06, 0x03, 0x02, 0x00, 0x08, 0x26, 0x06, 0x06, 0x01, 0x01, 0x0B, - 0x01, 0x06, 0x08, 0x00, 0x00, 0x8B, 0x3F, 0x26, 0x06, 0x03, 0x01, 0x09, - 0x08, 0x00, 0x01, 0x40, 0x26, 0x06, 0x1E, 0x01, 0x00, 0x03, 0x00, 0x26, - 0x06, 0x0E, 0x26, 0x01, 0x01, 0x17, 0x02, 0x00, 0x08, 0x03, 0x00, 0x01, - 0x01, 0x11, 0x04, 0x6F, 0x25, 0x02, 0x00, 0x01, 0x01, 0x0B, 0x01, 0x06, - 0x08, 0x00, 0x00, 0x7F, 0x2D, 0x44, 0x11, 0x01, 0x01, 0x17, 0x35, 0x00, - 0x00, 0x9F, 0xCE, 0x26, 0x01, 0x07, 0x17, 0x01, 0x00, 0x38, 0x0E, 0x06, - 0x09, 0x25, 0x01, 0x10, 0x17, 0x06, 0x01, 0x9F, 0x04, 0x35, 0x01, 0x01, - 0x38, 0x0E, 0x06, 0x2C, 0x25, 0x25, 0x01, 0x00, 0x77, 0x3E, 0xB3, 0x88, - 0x2E, 0x01, 0x01, 0x0E, 0x01, 0x01, 0xA8, 0x37, 0x06, 0x17, 0x29, 0x1A, - 0x36, 0x06, 0x04, 0xCE, 0x25, 0x04, 0x78, 0x01, 0x80, 0x64, 0xC5, 0x01, - 0x01, 0x77, 0x3E, 0x01, 0x17, 0x87, 0x3E, 0x04, 0x01, 0x9F, 0x04, 0x03, - 0x72, 0x28, 0x25, 0x04, 0xFF, 0x34, 0x01, 0x26, 0x03, 0x00, 0x09, 0x26, - 0x58, 0x06, 0x02, 0x68, 0x28, 0x02, 0x00, 0x00, 0x00, 0x9A, 0x01, 0x0F, - 0x17, 0x00, 0x00, 0x76, 0x2E, 0x01, 0x00, 0x38, 0x0E, 0x06, 0x10, 0x25, - 0x26, 0x01, 0x01, 0x0D, 0x06, 0x03, 0x25, 0x01, 0x02, 0x76, 0x3E, 0x01, - 0x00, 0x04, 0x21, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x14, 0x25, 0x01, 0x00, - 0x76, 0x3E, 0x26, 0x01, 0x80, 0x64, 0x0E, 0x06, 0x05, 0x01, 0x82, 0x00, - 0x08, 0x28, 0x5A, 0x04, 0x07, 0x25, 0x01, 0x82, 0x00, 0x08, 0x28, 0x25, - 0x00, 0x00, 0x01, 0x00, 0x2F, 0x06, 0x05, 0x3A, 0xAC, 0x37, 0x04, 0x78, - 0x26, 0x06, 0x04, 0x01, 0x01, 0x8F, 0x3E, 0x00, 0x01, 0xBF, 0xAA, 0xBF, - 0xAA, 0xC1, 0x84, 0x44, 0x26, 0x03, 0x00, 0xB6, 0x9B, 0x9B, 0x02, 0x00, - 0x4D, 0x26, 0x58, 0x06, 0x0A, 0x01, 0x03, 0xA8, 0x06, 0x02, 0x72, 0x28, - 0x25, 0x04, 0x03, 0x5C, 0x8A, 0x3C, 0x00, 0x00, 0x2F, 0x06, 0x0B, 0x86, - 0x2E, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x72, 0x28, 0x04, 0x11, 0xCE, 0x01, - 0x07, 0x17, 0x26, 0x01, 0x02, 0x0D, 0x06, 0x06, 0x06, 0x02, 0x72, 0x28, - 0x04, 0x70, 0x25, 0xC2, 0x01, 0x01, 0x0D, 0x33, 0x37, 0x06, 0x02, 0x61, - 0x28, 0x26, 0x01, 0x01, 0xC8, 0x36, 0xB2, 0x00, 0x01, 0xB8, 0x01, 0x0B, - 0x0E, 0x05, 0x02, 0x72, 0x28, 0x26, 0x01, 0x03, 0x0E, 0x06, 0x08, 0xC0, - 0x06, 0x02, 0x68, 0x28, 0x44, 0x25, 0x00, 0x44, 0x57, 0xC0, 0xAA, 0x26, - 0x06, 0x23, 0xC0, 0xAA, 0x26, 0x56, 0x26, 0x06, 0x18, 0x26, 0x01, 0x82, - 0x00, 0x0F, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x26, 0x03, 0x00, - 0x84, 0x02, 0x00, 0xB6, 0x02, 0x00, 0x53, 0x04, 0x65, 0x9B, 0x54, 0x04, - 0x5A, 0x9B, 0x9B, 0x55, 0x26, 0x06, 0x02, 0x35, 0x00, 0x25, 0x2B, 0x00, - 0x00, 0x79, 0x2C, 0xA1, 0x01, 0x7F, 0xB0, 0x26, 0x58, 0x06, 0x02, 0x35, - 0x28, 0x26, 0x05, 0x02, 0x72, 0x28, 0x38, 0x17, 0x0D, 0x06, 0x02, 0x74, - 0x28, 0x3B, 0x00, 0x00, 0x9C, 0xB8, 0x01, 0x14, 0x0D, 0x06, 0x02, 0x72, - 0x28, 0x84, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0xB6, 0x9B, 0x84, 0x26, 0x01, - 0x0C, 0x08, 0x01, 0x0C, 0x30, 0x05, 0x02, 0x64, 0x28, 0x00, 0x00, 0xB9, - 0x06, 0x02, 0x72, 0x28, 0x06, 0x02, 0x66, 0x28, 0x00, 0x0A, 0xB8, 0x01, - 0x02, 0x0E, 0x05, 0x02, 0x72, 0x28, 0xBF, 0x03, 0x00, 0x02, 0x00, 0x95, - 0x2C, 0x0A, 0x02, 0x00, 0x94, 0x2C, 0x0F, 0x37, 0x06, 0x02, 0x73, 0x28, - 0x02, 0x00, 0x93, 0x2C, 0x0D, 0x06, 0x02, 0x6B, 0x28, 0x02, 0x00, 0x96, - 0x3C, 0x8C, 0x01, 0x20, 0xB6, 0x01, 0x00, 0x03, 0x01, 0xC1, 0x03, 0x02, - 0x02, 0x02, 0x01, 0x20, 0x0F, 0x06, 0x02, 0x70, 0x28, 0x84, 0x02, 0x02, - 0xB6, 0x02, 0x02, 0x8E, 0x2E, 0x0E, 0x02, 0x02, 0x01, 0x00, 0x0F, 0x17, - 0x06, 0x0B, 0x8D, 0x84, 0x02, 0x02, 0x30, 0x06, 0x04, 0x01, 0x7F, 0x03, - 0x01, 0x8D, 0x84, 0x02, 0x02, 0x31, 0x02, 0x02, 0x8E, 0x3E, 0x02, 0x00, - 0x92, 0x02, 0x01, 0x98, 0xBF, 0x26, 0xC3, 0x58, 0x06, 0x02, 0x62, 0x28, - 0x26, 0xCD, 0x02, 0x00, 0x01, 0x86, 0x03, 0x0A, 0x17, 0x06, 0x02, 0x62, - 0x28, 0x79, 0x02, 0x01, 0x98, 0xC1, 0x06, 0x02, 0x63, 0x28, 0x26, 0x06, - 0x81, 0x47, 0xBF, 0xAA, 0xA6, 0x03, 0x03, 0xA4, 0x03, 0x04, 0xA2, 0x03, - 0x05, 0xA5, 0x03, 0x06, 0xA7, 0x03, 0x07, 0xA3, 0x03, 0x08, 0x27, 0x03, - 0x09, 0x26, 0x06, 0x81, 0x18, 0xBF, 0x01, 0x00, 0x38, 0x0E, 0x06, 0x0F, - 0x25, 0x02, 0x03, 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x03, 0xBE, - 0x04, 0x80, 0x7F, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x02, 0x05, - 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x05, 0xBC, 0x04, 0x80, 0x6A, - 0x01, 0x83, 0xFE, 0x01, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x02, 0x04, 0x05, - 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x04, 0xBD, 0x04, 0x80, 0x53, 0x01, - 0x0D, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x06, 0x05, 0x02, 0x6C, 0x28, - 0x01, 0x00, 0x03, 0x06, 0xBA, 0x04, 0x3F, 0x01, 0x0A, 0x38, 0x0E, 0x06, - 0x0E, 0x25, 0x02, 0x07, 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x07, - 0xBA, 0x04, 0x2B, 0x01, 0x0B, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x08, - 0x05, 0x02, 0x6C, 0x28, 0x01, 0x00, 0x03, 0x08, 0xBA, 0x04, 0x17, 0x01, - 0x10, 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x02, 0x09, 0x05, 0x02, 0x6C, 0x28, - 0x01, 0x00, 0x03, 0x09, 0xAE, 0x04, 0x03, 0x6C, 0x28, 0x25, 0x04, 0xFE, - 0x64, 0x02, 0x04, 0x06, 0x0D, 0x02, 0x04, 0x01, 0x05, 0x0F, 0x06, 0x02, - 0x69, 0x28, 0x01, 0x01, 0x88, 0x3E, 0x9B, 0x04, 0x0C, 0xA4, 0x01, 0x05, - 0x0F, 0x06, 0x02, 0x69, 0x28, 0x01, 0x01, 0x88, 0x3E, 0x9B, 0x02, 0x01, - 0x00, 0x04, 0xB8, 0x01, 0x0C, 0x0E, 0x05, 0x02, 0x72, 0x28, 0xC1, 0x01, - 0x03, 0x0E, 0x05, 0x02, 0x6D, 0x28, 0xBF, 0x26, 0x7C, 0x3E, 0x26, 0x01, - 0x20, 0x10, 0x06, 0x02, 0x6D, 0x28, 0x40, 0x44, 0x11, 0x01, 0x01, 0x17, - 0x05, 0x02, 0x6D, 0x28, 0xC1, 0x26, 0x01, 0x81, 0x05, 0x0F, 0x06, 0x02, - 0x6D, 0x28, 0x26, 0x7E, 0x3E, 0x7D, 0x44, 0xB6, 0x92, 0x2C, 0x01, 0x86, - 0x03, 0x10, 0x03, 0x00, 0x79, 0x2C, 0xCB, 0x03, 0x01, 0x01, 0x02, 0x03, - 0x02, 0x02, 0x00, 0x06, 0x21, 0xC1, 0x26, 0x26, 0x01, 0x02, 0x0A, 0x44, - 0x01, 0x06, 0x0F, 0x37, 0x06, 0x02, 0x6D, 0x28, 0x03, 0x02, 0xC1, 0x02, - 0x01, 0x01, 0x01, 0x0B, 0x01, 0x03, 0x08, 0x0E, 0x05, 0x02, 0x6D, 0x28, - 0x04, 0x08, 0x02, 0x01, 0x06, 0x04, 0x01, 0x00, 0x03, 0x02, 0xBF, 0x26, - 0x03, 0x03, 0x26, 0x01, 0x84, 0x00, 0x0F, 0x06, 0x02, 0x6E, 0x28, 0x84, - 0x44, 0xB6, 0x02, 0x02, 0x02, 0x01, 0x02, 0x03, 0x50, 0x26, 0x06, 0x01, - 0x28, 0x25, 0x9B, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, 0x97, - 0x02, 0x01, 0x02, 0x00, 0x39, 0x26, 0x01, 0x00, 0x0E, 0x06, 0x02, 0x60, - 0x00, 0xD0, 0x04, 0x74, 0x02, 0x01, 0x00, 0x03, 0x00, 0xC1, 0xAA, 0x26, - 0x06, 0x80, 0x43, 0xC1, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01, - 0x81, 0x7F, 0x04, 0x2E, 0x01, 0x80, 0x40, 0x38, 0x0E, 0x06, 0x07, 0x25, - 0x01, 0x83, 0xFE, 0x00, 0x04, 0x20, 0x01, 0x80, 0x41, 0x38, 0x0E, 0x06, - 0x07, 0x25, 0x01, 0x84, 0x80, 0x00, 0x04, 0x12, 0x01, 0x80, 0x42, 0x38, - 0x0E, 0x06, 0x07, 0x25, 0x01, 0x88, 0x80, 0x00, 0x04, 0x04, 0x01, 0x00, - 0x44, 0x25, 0x02, 0x00, 0x37, 0x03, 0x00, 0x04, 0xFF, 0x39, 0x9B, 0x79, - 0x2C, 0xC9, 0x05, 0x09, 0x02, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x17, 0x03, - 0x00, 0x92, 0x2C, 0x01, 0x86, 0x03, 0x10, 0x06, 0x3A, 0xBB, 0x26, 0x81, - 0x3D, 0x41, 0x25, 0x26, 0x01, 0x08, 0x0B, 0x37, 0x01, 0x8C, 0x80, 0x00, - 0x37, 0x17, 0x02, 0x00, 0x17, 0x02, 0x00, 0x01, 0x8C, 0x80, 0x00, 0x17, - 0x06, 0x19, 0x26, 0x01, 0x81, 0x7F, 0x17, 0x06, 0x05, 0x01, 0x84, 0x80, - 0x00, 0x37, 0x26, 0x01, 0x83, 0xFE, 0x00, 0x17, 0x06, 0x05, 0x01, 0x88, - 0x80, 0x00, 0x37, 0x03, 0x00, 0x04, 0x09, 0x02, 0x00, 0x01, 0x8C, 0x88, - 0x01, 0x17, 0x03, 0x00, 0x16, 0xBF, 0xAA, 0x26, 0x06, 0x23, 0xBF, 0xAA, - 0x26, 0x15, 0x26, 0x06, 0x18, 0x26, 0x01, 0x82, 0x00, 0x0F, 0x06, 0x05, - 0x01, 0x82, 0x00, 0x04, 0x01, 0x26, 0x03, 0x01, 0x84, 0x02, 0x01, 0xB6, - 0x02, 0x01, 0x12, 0x04, 0x65, 0x9B, 0x13, 0x04, 0x5A, 0x9B, 0x14, 0x9B, - 0x02, 0x00, 0x2A, 0x00, 0x00, 0xB9, 0x26, 0x5A, 0x06, 0x07, 0x25, 0x06, - 0x02, 0x66, 0x28, 0x04, 0x74, 0x00, 0x00, 0xC2, 0x01, 0x03, 0xC0, 0x44, - 0x25, 0x44, 0x00, 0x00, 0xBF, 0xC6, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, - 0xBF, 0xAA, 0x26, 0x06, 0x80, 0x50, 0xC1, 0x03, 0x01, 0xC1, 0x03, 0x02, - 0x02, 0x01, 0x01, 0x08, 0x0E, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, 0x0C, - 0x06, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0B, 0x02, 0x00, - 0x37, 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x10, 0x02, 0x01, - 0x01, 0x06, 0x0C, 0x17, 0x02, 0x02, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x01, - 0x03, 0x0E, 0x37, 0x17, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, - 0x5D, 0x01, 0x02, 0x0B, 0x02, 0x01, 0x08, 0x0B, 0x37, 0x03, 0x00, 0x04, - 0xFF, 0x2C, 0x9B, 0x02, 0x00, 0x00, 0x00, 0xBF, 0x01, 0x01, 0x0E, 0x05, - 0x02, 0x65, 0x28, 0xC1, 0x01, 0x08, 0x08, 0x82, 0x2E, 0x0E, 0x05, 0x02, - 0x65, 0x28, 0x00, 0x00, 0xBF, 0x88, 0x2E, 0x05, 0x15, 0x01, 0x01, 0x0E, - 0x05, 0x02, 0x69, 0x28, 0xC1, 0x01, 0x00, 0x0E, 0x05, 0x02, 0x69, 0x28, - 0x01, 0x02, 0x88, 0x3E, 0x04, 0x1C, 0x01, 0x19, 0x0E, 0x05, 0x02, 0x69, - 0x28, 0xC1, 0x01, 0x18, 0x0E, 0x05, 0x02, 0x69, 0x28, 0x84, 0x01, 0x18, - 0xB6, 0x89, 0x84, 0x01, 0x18, 0x30, 0x05, 0x02, 0x69, 0x28, 0x00, 0x00, - 0xBF, 0x06, 0x02, 0x6A, 0x28, 0x00, 0x00, 0x01, 0x02, 0x97, 0xC2, 0x01, - 0x08, 0x0B, 0xC2, 0x08, 0x00, 0x00, 0x01, 0x03, 0x97, 0xC2, 0x01, 0x08, - 0x0B, 0xC2, 0x08, 0x01, 0x08, 0x0B, 0xC2, 0x08, 0x00, 0x00, 0x01, 0x01, - 0x97, 0xC2, 0x00, 0x00, 0x3A, 0x26, 0x58, 0x05, 0x01, 0x00, 0x25, 0xD0, - 0x04, 0x76, 0x02, 0x03, 0x00, 0x91, 0x2E, 0x03, 0x01, 0x01, 0x00, 0x26, - 0x02, 0x01, 0x0A, 0x06, 0x10, 0x26, 0x01, 0x01, 0x0B, 0x90, 0x08, 0x2C, - 0x02, 0x00, 0x0E, 0x06, 0x01, 0x00, 0x5C, 0x04, 0x6A, 0x25, 0x01, 0x7F, - 0x00, 0x00, 0x01, 0x15, 0x87, 0x3E, 0x44, 0x52, 0x25, 0x52, 0x25, 0x29, - 0x00, 0x00, 0x01, 0x01, 0x44, 0xC4, 0x00, 0x00, 0x44, 0x38, 0x97, 0x44, - 0x26, 0x06, 0x05, 0xC2, 0x25, 0x5D, 0x04, 0x78, 0x25, 0x00, 0x00, 0x26, - 0x01, 0x81, 0xAC, 0x00, 0x0E, 0x06, 0x04, 0x25, 0x01, 0x7F, 0x00, 0x9A, - 0x59, 0x00, 0x02, 0x03, 0x00, 0x79, 0x2C, 0x9A, 0x03, 0x01, 0x02, 0x01, - 0x01, 0x0F, 0x17, 0x02, 0x01, 0x01, 0x04, 0x11, 0x01, 0x0F, 0x17, 0x02, - 0x01, 0x01, 0x08, 0x11, 0x01, 0x0F, 0x17, 0x01, 0x00, 0x38, 0x0E, 0x06, - 0x10, 0x25, 0x01, 0x00, 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, - 0x01, 0x4A, 0x04, 0x81, 0x0D, 0x01, 0x01, 0x38, 0x0E, 0x06, 0x10, 0x25, - 0x01, 0x01, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, - 0x04, 0x80, 0x77, 0x01, 0x02, 0x38, 0x0E, 0x06, 0x10, 0x25, 0x01, 0x01, - 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x49, 0x04, 0x01, 0x4A, 0x04, 0x80, - 0x61, 0x01, 0x03, 0x38, 0x0E, 0x06, 0x0F, 0x25, 0x25, 0x01, 0x10, 0x02, - 0x00, 0x06, 0x03, 0x47, 0x04, 0x01, 0x48, 0x04, 0x80, 0x4C, 0x01, 0x04, - 0x38, 0x0E, 0x06, 0x0E, 0x25, 0x25, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, - 0x47, 0x04, 0x01, 0x48, 0x04, 0x38, 0x01, 0x05, 0x38, 0x0E, 0x06, 0x0C, - 0x25, 0x25, 0x02, 0x00, 0x06, 0x03, 0x4B, 0x04, 0x01, 0x4C, 0x04, 0x26, - 0x26, 0x01, 0x09, 0x0F, 0x06, 0x02, 0x68, 0x28, 0x44, 0x25, 0x26, 0x01, - 0x01, 0x17, 0x01, 0x04, 0x0B, 0x01, 0x10, 0x08, 0x44, 0x01, 0x08, 0x17, - 0x01, 0x10, 0x44, 0x09, 0x02, 0x00, 0x06, 0x03, 0x45, 0x04, 0x01, 0x46, - 0x00, 0x25, 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x02, 0x0F, 0x00, - 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x26, 0x5B, 0x44, 0x01, 0x03, 0x0A, 0x17, - 0x00, 0x00, 0x9A, 0x01, 0x0C, 0x11, 0x01, 0x01, 0x0E, 0x00, 0x00, 0x9A, - 0x01, 0x0C, 0x11, 0x5A, 0x00, 0x00, 0x9A, 0x01, 0x81, 0x70, 0x17, 0x01, - 0x20, 0x0D, 0x00, 0x00, 0x1B, 0x01, 0x00, 0x75, 0x2E, 0x26, 0x06, 0x22, - 0x01, 0x01, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01, 0x00, 0x9E, 0x04, 0x14, - 0x01, 0x02, 0x38, 0x0E, 0x06, 0x0D, 0x25, 0x77, 0x2E, 0x01, 0x01, 0x0E, - 0x06, 0x03, 0x01, 0x10, 0x37, 0x04, 0x01, 0x25, 0x04, 0x01, 0x25, 0x7B, - 0x2E, 0x05, 0x33, 0x2F, 0x06, 0x30, 0x86, 0x2E, 0x01, 0x14, 0x38, 0x0E, - 0x06, 0x06, 0x25, 0x01, 0x02, 0x37, 0x04, 0x22, 0x01, 0x15, 0x38, 0x0E, - 0x06, 0x09, 0x25, 0xAD, 0x06, 0x03, 0x01, 0x7F, 0x9E, 0x04, 0x13, 0x01, - 0x16, 0x38, 0x0E, 0x06, 0x06, 0x25, 0x01, 0x01, 0x37, 0x04, 0x07, 0x25, - 0x01, 0x04, 0x37, 0x01, 0x00, 0x25, 0x1A, 0x06, 0x03, 0x01, 0x08, 0x37, - 0x00, 0x00, 0x1B, 0x26, 0x05, 0x13, 0x2F, 0x06, 0x10, 0x86, 0x2E, 0x01, - 0x15, 0x0E, 0x06, 0x08, 0x25, 0xAD, 0x01, 0x00, 0x77, 0x3E, 0x04, 0x01, - 0x20, 0x00, 0x00, 0xCE, 0x01, 0x07, 0x17, 0x01, 0x01, 0x0F, 0x06, 0x02, - 0x72, 0x28, 0x00, 0x01, 0x03, 0x00, 0x29, 0x1A, 0x06, 0x05, 0x02, 0x00, - 0x87, 0x3E, 0x00, 0xCE, 0x25, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD1, 0x01, - 0x01, 0xDE, 0x29, 0x26, 0x01, 0x00, 0xC8, 0x01, 0x16, 0xD1, 0xD7, 0x29, - 0x00, 0x00, 0x01, 0x0B, 0xDE, 0x4E, 0x26, 0x26, 0x01, 0x03, 0x08, 0xDD, - 0xDD, 0x18, 0x26, 0x58, 0x06, 0x02, 0x25, 0x00, 0xDD, 0x1D, 0x26, 0x06, - 0x05, 0x84, 0x44, 0xD8, 0x04, 0x77, 0x25, 0x04, 0x6C, 0x00, 0x21, 0x01, - 0x0F, 0xDE, 0x26, 0x92, 0x2C, 0x01, 0x86, 0x03, 0x10, 0x06, 0x0C, 0x01, - 0x04, 0x08, 0xDD, 0x80, 0x2E, 0xDE, 0x78, 0x2E, 0xDE, 0x04, 0x02, 0x5E, - 0xDD, 0x26, 0xDC, 0x84, 0x44, 0xD8, 0x00, 0x02, 0xA4, 0xA6, 0x08, 0xA2, - 0x08, 0xA5, 0x08, 0xA7, 0x08, 0xA3, 0x08, 0x27, 0x08, 0x03, 0x00, 0x01, - 0x01, 0xDE, 0x01, 0x27, 0x8E, 0x2E, 0x08, 0x91, 0x2E, 0x01, 0x01, 0x0B, - 0x08, 0x02, 0x00, 0x06, 0x04, 0x5E, 0x02, 0x00, 0x08, 0x83, 0x2C, 0x38, - 0x09, 0x26, 0x5B, 0x06, 0x24, 0x02, 0x00, 0x05, 0x04, 0x44, 0x5E, 0x44, - 0x5F, 0x01, 0x04, 0x09, 0x26, 0x58, 0x06, 0x03, 0x25, 0x01, 0x00, 0x26, - 0x01, 0x04, 0x08, 0x02, 0x00, 0x08, 0x03, 0x00, 0x44, 0x01, 0x04, 0x08, - 0x38, 0x08, 0x44, 0x04, 0x03, 0x25, 0x01, 0x7F, 0x03, 0x01, 0xDD, 0x94, - 0x2C, 0xDC, 0x7A, 0x01, 0x04, 0x19, 0x7A, 0x01, 0x04, 0x08, 0x01, 0x1C, - 0x32, 0x7A, 0x01, 0x20, 0xD8, 0x8D, 0x8E, 0x2E, 0xDA, 0x91, 0x2E, 0x26, - 0x01, 0x01, 0x0B, 0xDC, 0x90, 0x44, 0x26, 0x06, 0x0F, 0x5D, 0x38, 0x2C, - 0x26, 0xC7, 0x05, 0x02, 0x62, 0x28, 0xDC, 0x44, 0x5E, 0x44, 0x04, 0x6E, - 0x60, 0x01, 0x01, 0xDE, 0x01, 0x00, 0xDE, 0x02, 0x00, 0x06, 0x81, 0x5A, - 0x02, 0x00, 0xDC, 0xA4, 0x06, 0x0E, 0x01, 0x83, 0xFE, 0x01, 0xDC, 0x89, - 0xA4, 0x01, 0x04, 0x09, 0x26, 0xDC, 0x5D, 0xDA, 0xA6, 0x06, 0x16, 0x01, - 0x00, 0xDC, 0x8B, 0xA6, 0x01, 0x04, 0x09, 0x26, 0xDC, 0x01, 0x02, 0x09, - 0x26, 0xDC, 0x01, 0x00, 0xDE, 0x01, 0x03, 0x09, 0xD9, 0xA2, 0x06, 0x0C, - 0x01, 0x01, 0xDC, 0x01, 0x01, 0xDC, 0x82, 0x2E, 0x01, 0x08, 0x09, 0xDE, - 0xA5, 0x06, 0x19, 0x01, 0x0D, 0xDC, 0xA5, 0x01, 0x04, 0x09, 0x26, 0xDC, - 0x01, 0x02, 0x09, 0xDC, 0x42, 0x06, 0x03, 0x01, 0x03, 0xDB, 0x43, 0x06, - 0x03, 0x01, 0x01, 0xDB, 0xA7, 0x26, 0x06, 0x36, 0x01, 0x0A, 0xDC, 0x01, - 0x04, 0x09, 0x26, 0xDC, 0x5F, 0xDC, 0x40, 0x01, 0x00, 0x26, 0x01, 0x82, - 0x80, 0x80, 0x80, 0x00, 0x17, 0x06, 0x0A, 0x01, 0xFD, 0xFF, 0xFF, 0xFF, - 0x7F, 0x17, 0x01, 0x1D, 0xDC, 0x26, 0x01, 0x20, 0x0A, 0x06, 0x0C, 0xA0, - 0x11, 0x01, 0x01, 0x17, 0x06, 0x02, 0x26, 0xDC, 0x5C, 0x04, 0x6E, 0x60, - 0x04, 0x01, 0x25, 0xA3, 0x06, 0x0A, 0x01, 0x0B, 0xDC, 0x01, 0x02, 0xDC, - 0x01, 0x82, 0x00, 0xDC, 0x27, 0x26, 0x06, 0x1F, 0x01, 0x10, 0xDC, 0x01, - 0x04, 0x09, 0x26, 0xDC, 0x5F, 0xDC, 0x85, 0x2C, 0x01, 0x00, 0xA0, 0x0F, - 0x06, 0x0A, 0x26, 0x1E, 0x26, 0xDE, 0x84, 0x44, 0xD8, 0x5C, 0x04, 0x72, - 0x60, 0x04, 0x01, 0x25, 0x02, 0x01, 0x58, 0x05, 0x11, 0x01, 0x15, 0xDC, - 0x02, 0x01, 0x26, 0xDC, 0x26, 0x06, 0x06, 0x5D, 0x01, 0x00, 0xDE, 0x04, - 0x77, 0x25, 0x00, 0x00, 0x01, 0x10, 0xDE, 0x79, 0x2C, 0x26, 0xCC, 0x06, - 0x0C, 0xAB, 0x23, 0x26, 0x5E, 0xDD, 0x26, 0xDC, 0x84, 0x44, 0xD8, 0x04, - 0x0D, 0x26, 0xCA, 0x44, 0xAB, 0x22, 0x26, 0x5C, 0xDD, 0x26, 0xDE, 0x84, - 0x44, 0xD8, 0x00, 0x00, 0x9C, 0x01, 0x14, 0xDE, 0x01, 0x0C, 0xDD, 0x84, - 0x01, 0x0C, 0xD8, 0x00, 0x00, 0x51, 0x26, 0x01, 0x00, 0x0E, 0x06, 0x02, - 0x60, 0x00, 0xCE, 0x25, 0x04, 0x73, 0x00, 0x26, 0xDC, 0xD8, 0x00, 0x00, - 0x26, 0xDE, 0xD8, 0x00, 0x01, 0x03, 0x00, 0x41, 0x25, 0x26, 0x01, 0x10, - 0x17, 0x06, 0x06, 0x01, 0x04, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x08, - 0x17, 0x06, 0x06, 0x01, 0x03, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x20, - 0x17, 0x06, 0x06, 0x01, 0x05, 0xDE, 0x02, 0x00, 0xDE, 0x26, 0x01, 0x80, - 0x40, 0x17, 0x06, 0x06, 0x01, 0x06, 0xDE, 0x02, 0x00, 0xDE, 0x01, 0x04, - 0x17, 0x06, 0x06, 0x01, 0x02, 0xDE, 0x02, 0x00, 0xDE, 0x00, 0x00, 0x26, - 0x01, 0x08, 0x4F, 0xDE, 0xDE, 0x00, 0x00, 0x26, 0x01, 0x10, 0x4F, 0xDE, - 0xDC, 0x00, 0x00, 0x26, 0x52, 0x06, 0x02, 0x25, 0x00, 0xCE, 0x25, 0x04, - 0x76 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 15, - 20, - 25, - 30, - 35, - 40, - 44, - 48, - 52, - 56, - 60, - 64, - 68, - 72, - 76, - 80, - 84, - 88, - 92, - 96, - 100, - 104, - 108, - 112, - 116, - 120, - 124, - 129, - 134, - 139, - 144, - 149, - 154, - 159, - 164, - 169, - 174, - 179, - 184, - 189, - 194, - 199, - 204, - 209, - 214, - 219, - 224, - 229, - 234, - 239, - 244, - 249, - 254, - 259, - 264, - 269, - 274, - 279, - 284, - 289, - 294, - 303, - 316, - 320, - 345, - 351, - 370, - 381, - 422, - 542, - 546, - 611, - 626, - 637, - 655, - 684, - 694, - 730, - 740, - 818, - 832, - 838, - 897, - 916, - 951, - 1000, - 1076, - 1103, - 1134, - 1145, - 1497, - 1644, - 1668, - 1884, - 1898, - 1907, - 1911, - 2006, - 2027, - 2083, - 2090, - 2101, - 2117, - 2123, - 2134, - 2169, - 2181, - 2187, - 2202, - 2218, - 2411, - 2420, - 2433, - 2442, - 2449, - 2459, - 2565, - 2590, - 2603, - 2619, - 2637, - 2669, - 2703, - 3071, - 3107, - 3120, - 3134, - 3139, - 3144, - 3210, - 3218, - 3226 -}; - -#define T0_INTERPRETED 88 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_ssl_hs_client_init_main, 169) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_ssl_hs_client_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* * */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a * b); - - } - break; - case 8: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 9: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 10: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 11: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 12: { - /* <= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a <= b)); - - } - break; - case 13: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 14: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 15: { - /* > */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a > b)); - - } - break; - case 16: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 17: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 18: { - /* anchor-dn-append-name */ - - size_t len; - - len = T0_POP(); - if (CTX->client_auth_vtable != NULL) { - (*CTX->client_auth_vtable)->append_name( - CTX->client_auth_vtable, ENG->pad, len); - } - - } - break; - case 19: { - /* anchor-dn-end-name */ - - if (CTX->client_auth_vtable != NULL) { - (*CTX->client_auth_vtable)->end_name( - CTX->client_auth_vtable); - } - - } - break; - case 20: { - /* anchor-dn-end-name-list */ - - if (CTX->client_auth_vtable != NULL) { - (*CTX->client_auth_vtable)->end_name_list( - CTX->client_auth_vtable); - } - - } - break; - case 21: { - /* anchor-dn-start-name */ - - size_t len; - - len = T0_POP(); - if (CTX->client_auth_vtable != NULL) { - (*CTX->client_auth_vtable)->start_name( - CTX->client_auth_vtable, len); - } - - } - break; - case 22: { - /* anchor-dn-start-name-list */ - - if (CTX->client_auth_vtable != NULL) { - (*CTX->client_auth_vtable)->start_name_list( - CTX->client_auth_vtable); - } - - } - break; - case 23: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 24: { - /* begin-cert */ - - if (ENG->chain_len == 0) { - T0_PUSHi(-1); - } else { - ENG->cert_cur = ENG->chain->data; - ENG->cert_len = ENG->chain->data_len; - ENG->chain ++; - ENG->chain_len --; - T0_PUSH(ENG->cert_len); - } - - } - break; - case 25: { - /* bzero */ - - size_t len = (size_t)T0_POP(); - void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - memset(addr, 0, len); - - } - break; - case 26: { - /* can-output? */ - - T0_PUSHi(-(ENG->hlen_out > 0)); - - } - break; - case 27: { - /* co */ - T0_CO(); - } - break; - case 28: { - /* compute-Finished-inner */ - - int prf_id = T0_POP(); - int from_client = T0_POPi(); - unsigned char tmp[48]; - br_tls_prf_seed_chunk seed; - - br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); - seed.data = tmp; - if (ENG->session.version >= BR_TLS12) { - seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); - } else { - br_multihash_out(&ENG->mhash, br_md5_ID, tmp); - br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); - seed.len = 36; - } - prf(ENG->pad, 12, ENG->session.master_secret, - sizeof ENG->session.master_secret, - from_client ? "client finished" : "server finished", - 1, &seed); - - } - break; - case 29: { - /* copy-cert-chunk */ - - size_t clen; - - clen = ENG->cert_len; - if (clen > sizeof ENG->pad) { - clen = sizeof ENG->pad; - } - memcpy(ENG->pad, ENG->cert_cur, clen); - ENG->cert_cur += clen; - ENG->cert_len -= clen; - T0_PUSH(clen); - - } - break; - case 30: { - /* copy-protocol-name */ - - size_t idx = T0_POP(); - size_t len = strlen(ENG->protocol_names[idx]); - memcpy(ENG->pad, ENG->protocol_names[idx], len); - T0_PUSH(len); - - } - break; - case 31: { - /* data-get8 */ - - size_t addr = T0_POP(); - T0_PUSH(t0_datablock[addr]); - - } - break; - case 32: { - /* discard-input */ - - ENG->hlen_in = 0; - - } - break; - case 33: { - /* do-client-sign */ - - size_t sig_len; - - sig_len = make_client_sign(CTX); - if (sig_len == 0) { - br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); - T0_CO(); - } - T0_PUSH(sig_len); - - } - break; - case 34: { - /* do-ecdh */ - - unsigned prf_id = T0_POP(); - unsigned ecdhe = T0_POP(); - int x; - - x = make_pms_ecdh(CTX, ecdhe, prf_id); - if (x < 0) { - br_ssl_engine_fail(ENG, -x); - T0_CO(); - } else { - T0_PUSH(x); - } - - } - break; - case 35: { - /* do-rsa-encrypt */ - - int x; - - x = make_pms_rsa(CTX, T0_POP()); - if (x < 0) { - br_ssl_engine_fail(ENG, -x); - T0_CO(); - } else { - T0_PUSH(x); - } - - } - break; - case 36: { - /* do-static-ecdh */ - - unsigned prf_id = T0_POP(); - - if (make_pms_static_ecdh(CTX, prf_id) < 0) { - br_ssl_engine_fail(ENG, BR_ERR_INVALID_ALGORITHM); - T0_CO(); - } - - } - break; - case 37: { - /* drop */ - (void)T0_POP(); - } - break; - case 38: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 39: { - /* ext-ALPN-length */ - - size_t u, len; - - if (ENG->protocol_names_num == 0) { - T0_PUSH(0); - T0_RET(); - } - len = 6; - for (u = 0; u < ENG->protocol_names_num; u ++) { - len += 1 + strlen(ENG->protocol_names[u]); - } - T0_PUSH(len); - - } - break; - case 40: { - /* fail */ - - br_ssl_engine_fail(ENG, (int)T0_POPi()); - T0_CO(); - - } - break; - case 41: { - /* flush-record */ - - br_ssl_engine_flush_record(ENG); - - } - break; - case 42: { - /* get-client-chain */ - - uint32_t auth_types; - - auth_types = T0_POP(); - if (CTX->client_auth_vtable != NULL) { - br_ssl_client_certificate ux; - - (*CTX->client_auth_vtable)->choose(CTX->client_auth_vtable, - CTX, auth_types, &ux); - CTX->auth_type = (unsigned char)ux.auth_type; - CTX->hash_id = (unsigned char)ux.hash_id; - ENG->chain = ux.chain; - ENG->chain_len = ux.chain_len; - } else { - CTX->hash_id = 0; - ENG->chain_len = 0; - } - - } - break; - case 43: { - /* get-key-type-usages */ - - const br_x509_class *xc; - const br_x509_pkey *pk; - unsigned usages; - - xc = *(ENG->x509ctx); - pk = xc->get_pkey(ENG->x509ctx, &usages); - if (pk == NULL) { - T0_PUSH(0); - } else { - T0_PUSH(pk->key_type | usages); - } - - } - break; - case 44: { - /* get16 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); - - } - break; - case 45: { - /* get32 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); - - } - break; - case 46: { - /* get8 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*((unsigned char *)ENG + addr)); - - } - break; - case 47: { - /* has-input? */ - - T0_PUSHi(-(ENG->hlen_in != 0)); - - } - break; - case 48: { - /* memcmp */ - - size_t len = (size_t)T0_POP(); - void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); - void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); - int x = memcmp(addr1, addr2, len); - T0_PUSH((uint32_t)-(x == 0)); - - } - break; - case 49: { - /* memcpy */ - - size_t len = (size_t)T0_POP(); - void *src = (unsigned char *)ENG + (size_t)T0_POP(); - void *dst = (unsigned char *)ENG + (size_t)T0_POP(); - memcpy(dst, src, len); - - } - break; - case 50: { - /* mkrand */ - - size_t len = (size_t)T0_POP(); - void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - br_hmac_drbg_generate(&ENG->rng, addr, len); - - } - break; - case 51: { - /* more-incoming-bytes? */ - - T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); - - } - break; - case 52: { - /* multihash-init */ - - br_multihash_init(&ENG->mhash); - - } - break; - case 53: { - /* neg */ - - uint32_t a = T0_POP(); - T0_PUSH(-a); - - } - break; - case 54: { - /* not */ - - uint32_t a = T0_POP(); - T0_PUSH(~a); - - } - break; - case 55: { - /* or */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a | b); - - } - break; - case 56: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 57: { - /* read-chunk-native */ - - size_t clen = ENG->hlen_in; - if (clen > 0) { - uint32_t addr, len; - - len = T0_POP(); - addr = T0_POP(); - if ((size_t)len < clen) { - clen = (size_t)len; - } - memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); - if (ENG->record_type_in == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); - } - T0_PUSH(addr + (uint32_t)clen); - T0_PUSH(len - (uint32_t)clen); - ENG->hbuf_in += clen; - ENG->hlen_in -= clen; - } - - } - break; - case 58: { - /* read8-native */ - - if (ENG->hlen_in > 0) { - unsigned char x; - - x = *ENG->hbuf_in ++; - if (ENG->record_type_in == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, &x, 1); - } - T0_PUSH(x); - ENG->hlen_in --; - } else { - T0_PUSHi(-1); - } - - } - break; - case 59: { - /* set-server-curve */ - - const br_x509_class *xc; - const br_x509_pkey *pk; - - xc = *(ENG->x509ctx); - pk = xc->get_pkey(ENG->x509ctx, NULL); - CTX->server_curve = - (pk->key_type == BR_KEYTYPE_EC) ? pk->key.ec.curve : 0; - - } - break; - case 60: { - /* set16 */ - - size_t addr = (size_t)T0_POP(); - *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); - - } - break; - case 61: { - /* set32 */ - - size_t addr = (size_t)T0_POP(); - *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); - - } - break; - case 62: { - /* set8 */ - - size_t addr = (size_t)T0_POP(); - *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); - - } - break; - case 63: { - /* strlen */ - - void *str = (unsigned char *)ENG + (size_t)T0_POP(); - T0_PUSH((uint32_t)strlen(str)); - - } - break; - case 64: { - /* supported-curves */ - - uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; - T0_PUSH(x); - - } - break; - case 65: { - /* supported-hash-functions */ - - int i; - unsigned x, num; - - x = 0; - num = 0; - for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { - if (br_multihash_getimpl(&ENG->mhash, i)) { - x |= 1U << i; - num ++; - } - } - T0_PUSH(x); - T0_PUSH(num); - - } - break; - case 66: { - /* supports-ecdsa? */ - - T0_PUSHi(-(ENG->iecdsa != 0)); - - } - break; - case 67: { - /* supports-rsa-sign? */ - - T0_PUSHi(-(ENG->irsavrfy != 0)); - - } - break; - case 68: { - /* swap */ - T0_SWAP(); - } - break; - case 69: { - /* switch-aesccm-in */ - - int is_client, prf_id; - unsigned cipher_key_len, tag_len; - - tag_len = T0_POP(); - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, - ENG->iaes_ctrcbc, cipher_key_len, tag_len); - - } - break; - case 70: { - /* switch-aesccm-out */ - - int is_client, prf_id; - unsigned cipher_key_len, tag_len; - - tag_len = T0_POP(); - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, - ENG->iaes_ctrcbc, cipher_key_len, tag_len); - - } - break; - case 71: { - /* switch-aesgcm-in */ - - int is_client, prf_id; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, - ENG->iaes_ctr, cipher_key_len); - - } - break; - case 72: { - /* switch-aesgcm-out */ - - int is_client, prf_id; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, - ENG->iaes_ctr, cipher_key_len); - - } - break; - case 73: { - /* switch-cbc-in */ - - int is_client, prf_id, mac_id, aes; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - aes = T0_POP(); - mac_id = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, - aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); - - } - break; - case 74: { - /* switch-cbc-out */ - - int is_client, prf_id, mac_id, aes; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - aes = T0_POP(); - mac_id = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, - aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); - - } - break; - case 75: { - /* switch-chapol-in */ - - int is_client, prf_id; - - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); - - } - break; - case 76: { - /* switch-chapol-out */ - - int is_client, prf_id; - - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); - - } - break; - case 77: { - /* test-protocol-name */ - - size_t len = T0_POP(); - size_t u; - - for (u = 0; u < ENG->protocol_names_num; u ++) { - const char *name; - - name = ENG->protocol_names[u]; - if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { - T0_PUSH(u); - T0_RET(); - } - } - T0_PUSHi(-1); - - } - break; - case 78: { - /* total-chain-length */ - - size_t u; - uint32_t total; - - total = 0; - for (u = 0; u < ENG->chain_len; u ++) { - total += 3 + (uint32_t)ENG->chain[u].data_len; - } - T0_PUSH(total); - - } - break; - case 79: { - /* u>> */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x >> c); - - } - break; - case 80: { - /* verify-SKE-sig */ - - size_t sig_len = T0_POP(); - int use_rsa = T0_POPi(); - int hash = T0_POPi(); - - T0_PUSH(verify_SKE_sig(CTX, hash, use_rsa, sig_len)); - - } - break; - case 81: { - /* write-blob-chunk */ - - size_t clen = ENG->hlen_out; - if (clen > 0) { - uint32_t addr, len; - - len = T0_POP(); - addr = T0_POP(); - if ((size_t)len < clen) { - clen = (size_t)len; - } - memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); - if (ENG->record_type_out == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); - } - T0_PUSH(addr + (uint32_t)clen); - T0_PUSH(len - (uint32_t)clen); - ENG->hbuf_out += clen; - ENG->hlen_out -= clen; - } - - } - break; - case 82: { - /* write8-native */ - - unsigned char x; - - x = (unsigned char)T0_POP(); - if (ENG->hlen_out > 0) { - if (ENG->record_type_out == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, &x, 1); - } - *ENG->hbuf_out ++ = x; - ENG->hlen_out --; - T0_PUSHi(-1); - } else { - T0_PUSHi(0); - } - - } - break; - case 83: { - /* x509-append */ - - const br_x509_class *xc; - size_t len; - - xc = *(ENG->x509ctx); - len = T0_POP(); - xc->append(ENG->x509ctx, ENG->pad, len); - - } - break; - case 84: { - /* x509-end-cert */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - xc->end_cert(ENG->x509ctx); - - } - break; - case 85: { - /* x509-end-chain */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - T0_PUSH(xc->end_chain(ENG->x509ctx)); - - } - break; - case 86: { - /* x509-start-cert */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - xc->start_cert(ENG->x509ctx, T0_POP()); - - } - break; - case 87: { - /* x509-start-chain */ - - const br_x509_class *xc; - uint32_t bc; - - bc = T0_POP(); - xc = *(ENG->x509ctx); - xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL); - - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_hs_server.c b/src/tls/bearssl/ssl_hs_server.c deleted file mode 100644 index 7fc29b3c0..000000000 --- a/src/tls/bearssl/ssl_hs_server.c +++ /dev/null @@ -1,2014 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_ssl_hs_server_init_main(void *t0ctx); - -void br_ssl_hs_server_run(void *t0ctx); - - - -#include -#include - -#include "inner.h" - -/* - * This macro evaluates to a pointer to the current engine context. - */ -#define ENG ((br_ssl_engine_context *)(void *)((unsigned char *)t0ctx - offsetof(br_ssl_engine_context, cpu))) - - - - - -/* - * This macro evaluates to a pointer to the server context, under that - * specific name. It must be noted that since the engine context is the - * first field of the br_ssl_server_context structure ('eng'), then - * pointers values of both types are interchangeable, modulo an - * appropriate cast. This also means that "addresses" computed as offsets - * within the structure work for both kinds of context. - */ -#define CTX ((br_ssl_server_context *)ENG) - -/* - * Decrypt the pre-master secret (RSA key exchange). - */ -static void -do_rsa_decrypt(br_ssl_server_context *ctx, int prf_id, - unsigned char *epms, size_t len) -{ - uint32_t x; - unsigned char rpms[48]; - - /* - * Decrypt the PMS. - */ - x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, epms, &len); - - /* - * Set the first two bytes to the maximum supported client - * protocol version. These bytes are used for version rollback - * detection; forceing the two bytes will make the master secret - * wrong if the bytes are not correct. This process is - * recommended by RFC 5246 (section 7.4.7.1). - */ - br_enc16be(epms, ctx->client_max_version); - - /* - * Make a random PMS and copy it above the decrypted value if the - * decryption failed. Note that we use a constant-time conditional - * copy. - */ - br_hmac_drbg_generate(&ctx->eng.rng, rpms, sizeof rpms); - br_ccopy(x ^ 1, epms, rpms, sizeof rpms); - - /* - * Compute master secret. - */ - br_ssl_engine_compute_master(&ctx->eng, prf_id, epms, 48); - - /* - * Clear the pre-master secret from RAM: it is normally a buffer - * in the context, hence potentially long-lived. - */ - memset(epms, 0, len); -} - -/* - * Common part for ECDH and ECDHE. - */ -static void -ecdh_common(br_ssl_server_context *ctx, int prf_id, - unsigned char *xcoor, size_t xcoor_len, uint32_t ctl) -{ - unsigned char rpms[80]; - - if (xcoor_len > sizeof rpms) { - xcoor_len = sizeof rpms; - ctl = 0; - } - - /* - * Make a random PMS and copy it above the decrypted value if the - * decryption failed. Note that we use a constant-time conditional - * copy. - */ - br_hmac_drbg_generate(&ctx->eng.rng, rpms, xcoor_len); - br_ccopy(ctl ^ 1, xcoor, rpms, xcoor_len); - - /* - * Compute master secret. - */ - br_ssl_engine_compute_master(&ctx->eng, prf_id, xcoor, xcoor_len); - - /* - * Clear the pre-master secret from RAM: it is normally a buffer - * in the context, hence potentially long-lived. - */ - memset(xcoor, 0, xcoor_len); -} - -/* - * Do the ECDH key exchange (not ECDHE). - */ -static void -do_ecdh(br_ssl_server_context *ctx, int prf_id, - unsigned char *cpoint, size_t cpoint_len) -{ - uint32_t x; - - /* - * Finalise the key exchange. - */ - x = (*ctx->policy_vtable)->do_keyx(ctx->policy_vtable, - cpoint, &cpoint_len); - ecdh_common(ctx, prf_id, cpoint, cpoint_len, x); -} - -/* - * Do the full static ECDH key exchange. When this function is called, - * it has already been verified that the cipher suite uses ECDH (not ECDHE), - * and the client's public key (from its certificate) has type EC and is - * apt for key exchange. - */ -static void -do_static_ecdh(br_ssl_server_context *ctx, int prf_id) -{ - unsigned char cpoint[133]; - size_t cpoint_len; - const br_x509_class **xc; - const br_x509_pkey *pk; - - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - cpoint_len = pk->key.ec.qlen; - if (cpoint_len > sizeof cpoint) { - /* - * If the point is larger than our buffer then we need to - * restrict it. Length 2 is not a valid point length, so - * the ECDH will fail. - */ - cpoint_len = 2; - } - memcpy(cpoint, pk->key.ec.q, cpoint_len); - do_ecdh(ctx, prf_id, cpoint, cpoint_len); -} - -static size_t -hash_data(br_ssl_server_context *ctx, - void *dst, int hash_id, const void *src, size_t len) -{ - const br_hash_class *hf; - br_hash_compat_context hc; - - if (hash_id == 0) { - unsigned char tmp[36]; - - hf = br_multihash_getimpl(&ctx->eng.mhash, br_md5_ID); - if (hf == NULL) { - return 0; - } - hf->init(&hc.vtable); - hf->update(&hc.vtable, src, len); - hf->out(&hc.vtable, tmp); - hf = br_multihash_getimpl(&ctx->eng.mhash, br_sha1_ID); - if (hf == NULL) { - return 0; - } - hf->init(&hc.vtable); - hf->update(&hc.vtable, src, len); - hf->out(&hc.vtable, tmp + 16); - memcpy(dst, tmp, 36); - return 36; - } else { - hf = br_multihash_getimpl(&ctx->eng.mhash, hash_id); - if (hf == NULL) { - return 0; - } - hf->init(&hc.vtable); - hf->update(&hc.vtable, src, len); - hf->out(&hc.vtable, dst); - return (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; - } -} - -/* - * Do the ECDHE key exchange (part 1: generation of transient key, and - * computing of the point to send to the client). Returned value is the - * signature length (in bytes), or -x on error (with x being an error - * code). The encoded point is written in the ecdhe_point[] context buffer - * (length in ecdhe_point_len). - */ -static int -do_ecdhe_part1(br_ssl_server_context *ctx, int curve) -{ - unsigned algo_id; - unsigned mask; - const unsigned char *order; - size_t olen, glen; - size_t hv_len, sig_len; - - if (!((ctx->eng.iec->supported_curves >> curve) & 1)) { - return -BR_ERR_INVALID_ALGORITHM; - } - ctx->eng.ecdhe_curve = curve; - - /* - * Generate our private key. We need a non-zero random value - * which is lower than the curve order, in a "large enough" - * range. We force the top bit to 0 and bottom bit to 1, which - * does the trick. Note that contrary to what happens in ECDSA, - * this is not a problem if we do not cover the full range of - * possible values. - */ - order = ctx->eng.iec->order(curve, &olen); - mask = 0xFF; - while (mask >= order[0]) { - mask >>= 1; - } - br_hmac_drbg_generate(&ctx->eng.rng, ctx->ecdhe_key, olen); - ctx->ecdhe_key[0] &= mask; - ctx->ecdhe_key[olen - 1] |= 0x01; - ctx->ecdhe_key_len = olen; - - /* - * Compute our ECDH point. - */ - glen = ctx->eng.iec->mulgen(ctx->eng.ecdhe_point, - ctx->ecdhe_key, olen, curve); - ctx->eng.ecdhe_point_len = glen; - - /* - * Assemble the message to be signed, and possibly hash it. - */ - memcpy(ctx->eng.pad, ctx->eng.client_random, 32); - memcpy(ctx->eng.pad + 32, ctx->eng.server_random, 32); - ctx->eng.pad[64 + 0] = 0x03; - ctx->eng.pad[64 + 1] = 0x00; - ctx->eng.pad[64 + 2] = curve; - ctx->eng.pad[64 + 3] = ctx->eng.ecdhe_point_len; - memcpy(ctx->eng.pad + 64 + 4, - ctx->eng.ecdhe_point, ctx->eng.ecdhe_point_len); - hv_len = 64 + 4 + ctx->eng.ecdhe_point_len; - algo_id = ctx->sign_hash_id; - if (algo_id >= (unsigned)0xFF00) { - hv_len = hash_data(ctx, ctx->eng.pad, algo_id & 0xFF, - ctx->eng.pad, hv_len); - if (hv_len == 0) { - return -BR_ERR_INVALID_ALGORITHM; - } - } - - sig_len = (*ctx->policy_vtable)->do_sign(ctx->policy_vtable, - algo_id, ctx->eng.pad, hv_len, sizeof ctx->eng.pad); - return sig_len ? (int)sig_len : -BR_ERR_INVALID_ALGORITHM; -} - -/* - * Do the ECDHE key exchange (part 2: computation of the shared secret - * from the point sent by the client). - */ -static void -do_ecdhe_part2(br_ssl_server_context *ctx, int prf_id, - unsigned char *cpoint, size_t cpoint_len) -{ - int curve; - uint32_t ctl; - size_t xoff, xlen; - - curve = ctx->eng.ecdhe_curve; - - /* - * Finalise the key exchange. - */ - ctl = ctx->eng.iec->mul(cpoint, cpoint_len, - ctx->ecdhe_key, ctx->ecdhe_key_len, curve); - xoff = ctx->eng.iec->xoff(curve, &xlen); - ecdh_common(ctx, prf_id, cpoint + xoff, xlen, ctl); - - /* - * Clear the ECDHE private key. Forward Secrecy is achieved insofar - * as that key does not get stolen, so we'd better destroy it - * as soon as it ceases to be useful. - */ - memset(ctx->ecdhe_key, 0, ctx->ecdhe_key_len); -} - -/* - * Offset for hash value within the pad (when obtaining all hash values, - * in preparation for verification of the CertificateVerify message). - * Order is MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512; last value - * is used to get the total length. - */ -static const unsigned char HASH_PAD_OFF[] = { 0, 16, 36, 64, 96, 144, 208 }; - -/* - * OID for hash functions in RSA signatures. - */ -static const unsigned char HASH_OID_SHA1[] = { - 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A -}; - -static const unsigned char HASH_OID_SHA224[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 -}; - -static const unsigned char HASH_OID_SHA256[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 -}; - -static const unsigned char HASH_OID_SHA384[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 -}; - -static const unsigned char HASH_OID_SHA512[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 -}; - -static const unsigned char *HASH_OID[] = { - HASH_OID_SHA1, - HASH_OID_SHA224, - HASH_OID_SHA256, - HASH_OID_SHA384, - HASH_OID_SHA512 -}; - -/* - * Verify the signature in CertificateVerify. Returned value is 0 on - * success, or a non-zero error code. Lack of implementation of the - * designated signature algorithm is reported as a "bad signature" - * error (because it means that the peer did not honour our advertised - * set of supported signature algorithms). - */ -static int -verify_CV_sig(br_ssl_server_context *ctx, size_t sig_len) -{ - const br_x509_class **xc; - const br_x509_pkey *pk; - int id; - - id = ctx->hash_CV_id; - xc = ctx->eng.x509ctx; - pk = (*xc)->get_pkey(xc, NULL); - if (pk->key_type == BR_KEYTYPE_RSA) { - unsigned char tmp[64]; - const unsigned char *hash_oid; - - if (id == 0) { - hash_oid = NULL; - } else { - hash_oid = HASH_OID[id - 2]; - } - if (ctx->eng.irsavrfy == 0) { - return BR_ERR_BAD_SIGNATURE; - } - if (!ctx->eng.irsavrfy(ctx->eng.pad, sig_len, - hash_oid, ctx->hash_CV_len, &pk->key.rsa, tmp) - || memcmp(tmp, ctx->hash_CV, ctx->hash_CV_len) != 0) - { - return BR_ERR_BAD_SIGNATURE; - } - } else { - if (ctx->eng.iecdsa == 0) { - return BR_ERR_BAD_SIGNATURE; - } - if (!ctx->eng.iecdsa(ctx->eng.iec, - ctx->hash_CV, ctx->hash_CV_len, - &pk->key.ec, ctx->eng.pad, sig_len)) - { - return BR_ERR_BAD_SIGNATURE; - } - } - return 0; -} - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x00, 0x0A, 0x00, 0x24, 0x00, 0x2F, 0x01, 0x24, 0x00, 0x35, 0x02, - 0x24, 0x00, 0x3C, 0x01, 0x44, 0x00, 0x3D, 0x02, 0x44, 0x00, 0x9C, 0x03, - 0x04, 0x00, 0x9D, 0x04, 0x05, 0xC0, 0x03, 0x40, 0x24, 0xC0, 0x04, 0x41, - 0x24, 0xC0, 0x05, 0x42, 0x24, 0xC0, 0x08, 0x20, 0x24, 0xC0, 0x09, 0x21, - 0x24, 0xC0, 0x0A, 0x22, 0x24, 0xC0, 0x0D, 0x30, 0x24, 0xC0, 0x0E, 0x31, - 0x24, 0xC0, 0x0F, 0x32, 0x24, 0xC0, 0x12, 0x10, 0x24, 0xC0, 0x13, 0x11, - 0x24, 0xC0, 0x14, 0x12, 0x24, 0xC0, 0x23, 0x21, 0x44, 0xC0, 0x24, 0x22, - 0x55, 0xC0, 0x25, 0x41, 0x44, 0xC0, 0x26, 0x42, 0x55, 0xC0, 0x27, 0x11, - 0x44, 0xC0, 0x28, 0x12, 0x55, 0xC0, 0x29, 0x31, 0x44, 0xC0, 0x2A, 0x32, - 0x55, 0xC0, 0x2B, 0x23, 0x04, 0xC0, 0x2C, 0x24, 0x05, 0xC0, 0x2D, 0x43, - 0x04, 0xC0, 0x2E, 0x44, 0x05, 0xC0, 0x2F, 0x13, 0x04, 0xC0, 0x30, 0x14, - 0x05, 0xC0, 0x31, 0x33, 0x04, 0xC0, 0x32, 0x34, 0x05, 0xC0, 0x9C, 0x06, - 0x04, 0xC0, 0x9D, 0x07, 0x04, 0xC0, 0xA0, 0x08, 0x04, 0xC0, 0xA1, 0x09, - 0x04, 0xC0, 0xAC, 0x26, 0x04, 0xC0, 0xAD, 0x27, 0x04, 0xC0, 0xAE, 0x28, - 0x04, 0xC0, 0xAF, 0x29, 0x04, 0xCC, 0xA8, 0x15, 0x04, 0xCC, 0xA9, 0x25, - 0x04, 0x00, 0x00 -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x01, - 0x00, 0x0F, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x01, 0x08, - 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x02, 0x08, 0x00, 0x00, - 0x01, 0x02, 0x09, 0x00, 0x00, 0x29, 0x29, 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_CCS), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_FINISHED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_FRAGLEN), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_HANDSHAKE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_PARAM), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_SECRENEG), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_SIGNATURE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_BAD_VERSION), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_INVALID_ALGORITHM), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_NO_CLIENT_AUTH), 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OK), - 0x00, 0x00, 0x01, T0_INT1(BR_ERR_OVERSIZED_ID), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_UNEXPECTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_WRONG_KEY_USAGE), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, action)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, alert)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, application_data)), 0x00, 0x00, - 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, cipher_suite)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_server_context, client_max_version)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, client_random)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_server_context, client_suites)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_server_context, client_suites_num)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, close_received)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_server_context, curves)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, ecdhe_point_len)), - 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, flags)), - 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_server_context, hashes)), - 0x00, 0x00, 0x7B, 0x01, - T0_INT2(BR_MAX_CIPHER_SUITES * sizeof(br_suite_translated)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, log_max_frag_len)), - 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, pad)), 0x00, - 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, peer_log_max_frag_len)), 0x00, - 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, protocol_names_num)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, record_type_in)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, record_type_out)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, reneg)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, saved_finished)), 0x00, - 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, selected_protocol)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, server_name)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, server_random)), 0x00, 0x00, - 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, session_id_len)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, shutdown_recv)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_server_context, sign_hash_id)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_buf)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, suites_num)), 0x00, - 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, session) + offsetof(br_ssl_session_parameters, version)), - 0x00, 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_in)), - 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_ssl_engine_context, version_max)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_min)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(br_ssl_engine_context, version_out)), - 0x00, 0x00, 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x01, 0x03, 0x00, 0x9B, 0x2A, 0x63, 0x47, 0x9F, 0x2A, 0x05, - 0x04, 0x65, 0x01, 0x00, 0x00, 0x02, 0x00, 0x0F, 0x06, 0x02, 0x9F, 0x00, - 0x63, 0x04, 0x6B, 0x00, 0x06, 0x02, 0x6A, 0x2B, 0x00, 0x00, 0x2A, 0x8B, - 0x47, 0x05, 0x03, 0x01, 0x0C, 0x08, 0x47, 0x78, 0x2E, 0xA8, 0x1C, 0x85, - 0x01, 0x0C, 0x33, 0x00, 0x00, 0x2A, 0x22, 0x01, 0x08, 0x0C, 0x47, 0x61, - 0x22, 0x08, 0x00, 0x01, 0x03, 0x00, 0x77, 0x30, 0x02, 0x00, 0x38, 0x13, - 0x01, 0x01, 0x0C, 0x77, 0x42, 0x2C, 0x19, 0x38, 0x06, 0x07, 0x02, 0x00, - 0xD0, 0x03, 0x00, 0x04, 0x75, 0x01, 0x00, 0xC7, 0x02, 0x00, 0x2A, 0x19, - 0x13, 0x06, 0x02, 0x71, 0x2B, 0xD0, 0x04, 0x76, 0x00, 0x01, 0x00, 0x77, - 0x42, 0x01, 0x16, 0x89, 0x42, 0x01, 0x00, 0x8C, 0x40, 0x36, 0xB1, 0x35, - 0x06, 0x02, 0x73, 0x2B, 0x06, 0x0A, 0xD7, 0x01, 0x00, 0xD3, 0x01, 0x00, - 0xAD, 0x04, 0x80, 0x46, 0xD7, 0xD4, 0x29, 0xD9, 0x50, 0x06, 0x01, 0xD5, - 0xD8, 0x2C, 0x50, 0x06, 0x31, 0x01, 0x00, 0xAE, 0x2A, 0x5D, 0x06, 0x0F, - 0x01, 0x02, 0xA4, 0x05, 0x02, 0x37, 0x2B, 0x29, 0xB2, 0xB0, 0x2A, 0xC9, - 0x29, 0x04, 0x19, 0x2A, 0x5F, 0x06, 0x0B, 0x29, 0x01, 0x02, 0xA4, 0x05, - 0x02, 0x70, 0x2B, 0xB2, 0x04, 0x0A, 0xB4, 0x2A, 0x05, 0x04, 0x29, 0xAB, - 0x04, 0x02, 0xB3, 0xAF, 0x04, 0x01, 0xB2, 0x01, 0x00, 0xAD, 0x01, 0x00, - 0xD3, 0x3E, 0x01, 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x00, 0x00, - 0x3A, 0x3A, 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x38, 0x06, 0x04, 0xCF, - 0x29, 0x04, 0x78, 0x01, 0x02, 0x02, 0x00, 0xC6, 0x19, 0x38, 0x06, 0x04, - 0xCF, 0x29, 0x04, 0x78, 0x02, 0x00, 0x01, 0x84, 0x00, 0x08, 0x2B, 0x00, - 0x00, 0x81, 0x2F, 0x47, 0x12, 0x01, 0x01, 0x13, 0x37, 0x00, 0x00, 0x2A, - 0x05, 0x04, 0x29, 0x01, 0x7F, 0x00, 0x01, 0x00, 0xA2, 0x12, 0x01, 0x01, - 0x13, 0x5F, 0x06, 0x03, 0x61, 0x04, 0x75, 0x47, 0x29, 0x00, 0x00, 0x01, - 0x7F, 0xA1, 0xCF, 0x2A, 0x01, 0x07, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06, - 0x0D, 0x29, 0x01, 0x10, 0x13, 0x06, 0x05, 0x01, 0x00, 0x77, 0x42, 0xC5, - 0x04, 0x33, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x2A, 0x29, 0x29, 0x8A, 0x30, - 0x01, 0x01, 0x0F, 0x01, 0x01, 0xA4, 0x39, 0x06, 0x18, 0xC8, 0x2C, 0x19, - 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x80, 0x64, 0xC7, 0x01, - 0x01, 0x77, 0x42, 0x01, 0x17, 0x89, 0x42, 0x04, 0x03, 0x01, 0x00, 0xA1, - 0x04, 0x03, 0x73, 0x2B, 0x29, 0x04, 0xFF, 0x32, 0x01, 0x2A, 0x03, 0x00, - 0x09, 0x2A, 0x5D, 0x06, 0x02, 0x6A, 0x2B, 0x02, 0x00, 0x00, 0x00, 0x9C, - 0x01, 0x0F, 0x13, 0x00, 0x00, 0x76, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06, - 0x10, 0x29, 0x2A, 0x01, 0x01, 0x0E, 0x06, 0x03, 0x29, 0x01, 0x02, 0x76, - 0x42, 0x01, 0x00, 0x04, 0x21, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x14, 0x29, - 0x01, 0x00, 0x76, 0x42, 0x2A, 0x01, 0x80, 0x64, 0x0F, 0x06, 0x05, 0x01, - 0x82, 0x00, 0x08, 0x2B, 0x5F, 0x04, 0x07, 0x29, 0x01, 0x82, 0x00, 0x08, - 0x2B, 0x29, 0x00, 0x00, 0x01, 0x00, 0x31, 0x06, 0x05, 0x3D, 0xA9, 0x39, - 0x04, 0x78, 0x2A, 0x06, 0x04, 0x01, 0x01, 0x91, 0x42, 0x00, 0x00, 0x01, - 0x1F, 0x13, 0x01, 0x12, 0x0F, 0x05, 0x02, 0x74, 0x2B, 0x78, 0x2E, 0x2A, - 0xCB, 0x05, 0x02, 0x73, 0x2B, 0xA8, 0x28, 0x00, 0x02, 0x87, 0x2E, 0x05, - 0x02, 0xBC, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x7E, 0x03, 0x00, 0x2A, - 0x06, 0x17, 0xC2, 0x2A, 0x03, 0x01, 0x85, 0x47, 0xB6, 0x02, 0x01, 0x51, - 0x2A, 0x02, 0x00, 0x53, 0x06, 0x04, 0x03, 0x00, 0x04, 0x01, 0x29, 0x04, - 0x66, 0x9D, 0x9D, 0x02, 0x00, 0x61, 0x8C, 0x40, 0x00, 0x00, 0x31, 0x06, - 0x0B, 0x88, 0x30, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x04, 0x11, - 0xCF, 0x01, 0x07, 0x13, 0x2A, 0x01, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x02, - 0x73, 0x2B, 0x04, 0x70, 0x29, 0xC3, 0x01, 0x01, 0x0E, 0x35, 0x39, 0x06, - 0x02, 0x66, 0x2B, 0x2A, 0x01, 0x01, 0xCA, 0x38, 0xB5, 0x00, 0x01, 0xBA, - 0x01, 0x0B, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x2A, 0x01, 0x03, 0x0F, 0x06, - 0x08, 0xC1, 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x00, 0x47, 0x5C, 0xC1, - 0xA7, 0x2A, 0x06, 0x23, 0xC1, 0xA7, 0x2A, 0x5B, 0x2A, 0x06, 0x18, 0x2A, - 0x01, 0x82, 0x00, 0x10, 0x06, 0x05, 0x01, 0x82, 0x00, 0x04, 0x01, 0x2A, - 0x03, 0x00, 0x85, 0x02, 0x00, 0xB6, 0x02, 0x00, 0x58, 0x04, 0x65, 0x9D, - 0x59, 0x04, 0x5A, 0x9D, 0x9D, 0x5A, 0x2A, 0x06, 0x02, 0x37, 0x00, 0x29, - 0x2D, 0x00, 0x02, 0x2A, 0x01, 0x20, 0x13, 0x05, 0x02, 0x74, 0x2B, 0x01, - 0x0F, 0x13, 0x03, 0x00, 0xB0, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, - 0x23, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x61, 0x01, 0x01, 0x12, 0x02, - 0x00, 0x0F, 0x05, 0x02, 0x6C, 0x2B, 0x01, 0x08, 0x12, 0x2A, 0x01, 0x02, - 0x0B, 0x3A, 0x01, 0x06, 0x10, 0x39, 0x06, 0x02, 0x6E, 0x2B, 0x04, 0x0D, - 0x02, 0x00, 0x01, 0x01, 0x0F, 0x06, 0x04, 0x01, 0x00, 0x04, 0x02, 0x01, - 0x02, 0x20, 0x05, 0x02, 0x6E, 0x2B, 0xC0, 0x2A, 0x03, 0x01, 0x2A, 0x01, - 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x85, 0x47, 0xB6, 0x02, 0x01, - 0x55, 0x2A, 0x06, 0x01, 0x2B, 0x29, 0x9D, 0x00, 0x00, 0x1D, 0xBA, 0x01, - 0x0F, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x0A, 0xBA, 0x01, 0x01, 0x0F, - 0x05, 0x02, 0x73, 0x2B, 0xC0, 0x2A, 0x03, 0x00, 0x79, 0x40, 0x7A, 0x01, - 0x20, 0xB6, 0xC2, 0x2A, 0x01, 0x20, 0x10, 0x06, 0x02, 0x72, 0x2B, 0x2A, - 0x90, 0x42, 0x8F, 0x47, 0xB6, 0x1A, 0x03, 0x01, 0xC0, 0xA7, 0x01, 0x00, - 0x03, 0x02, 0x01, 0x00, 0x03, 0x03, 0x83, 0xA2, 0x17, 0x3A, 0x08, 0x03, - 0x04, 0x03, 0x05, 0x2A, 0x06, 0x80, 0x6D, 0xC0, 0x2A, 0x03, 0x06, 0x02, - 0x01, 0x06, 0x0A, 0x2A, 0x78, 0x2E, 0x0F, 0x06, 0x04, 0x01, 0x7F, 0x03, - 0x03, 0x2A, 0x01, 0x81, 0x7F, 0x0F, 0x06, 0x0A, 0x8A, 0x30, 0x06, 0x02, - 0x6B, 0x2B, 0x01, 0x7F, 0x03, 0x02, 0x2A, 0x01, 0x81, 0xAC, 0x00, 0x0F, - 0x06, 0x11, 0x02, 0x00, 0x98, 0x2E, 0x11, 0x02, 0x00, 0x97, 0x2E, 0x0B, - 0x13, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0xC4, 0x2A, 0x5D, 0x06, 0x03, - 0x29, 0x04, 0x26, 0x01, 0x00, 0xA4, 0x06, 0x0B, 0x01, 0x02, 0x0C, 0x7B, - 0x08, 0x02, 0x06, 0x47, 0x40, 0x04, 0x16, 0x29, 0x02, 0x05, 0x02, 0x04, - 0x11, 0x06, 0x02, 0x69, 0x2B, 0x02, 0x06, 0x02, 0x05, 0x40, 0x02, 0x05, - 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0xFF, 0x0F, 0x29, 0x01, 0x00, 0x03, - 0x07, 0xC2, 0xA7, 0x2A, 0x06, 0x09, 0xC2, 0x05, 0x04, 0x01, 0x7F, 0x03, - 0x07, 0x04, 0x74, 0x9D, 0x01, 0x00, 0x8D, 0x42, 0x01, 0x88, 0x04, 0x82, - 0x41, 0x01, 0x84, 0x80, 0x80, 0x00, 0x7E, 0x41, 0x2A, 0x06, 0x80, 0x4E, - 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x47, 0xC0, 0x01, 0x00, 0x3A, 0x0F, 0x06, - 0x04, 0x29, 0xB9, 0x04, 0x39, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29, - 0xB7, 0x04, 0x2F, 0x01, 0x83, 0xFE, 0x01, 0x3A, 0x0F, 0x06, 0x04, 0x29, - 0xB8, 0x04, 0x23, 0x01, 0x0D, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBE, 0x04, - 0x19, 0x01, 0x0A, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xBF, 0x04, 0x0F, 0x01, - 0x10, 0x3A, 0x0F, 0x06, 0x04, 0x29, 0xAC, 0x04, 0x05, 0x29, 0xBC, 0x01, - 0x00, 0x29, 0x04, 0xFF, 0x35, 0x9D, 0x9D, 0x02, 0x01, 0x02, 0x03, 0x13, - 0x03, 0x01, 0x02, 0x00, 0x5D, 0x06, 0x08, 0x79, 0x2E, 0x99, 0x40, 0x01, - 0x80, 0x56, 0xA3, 0x97, 0x2E, 0x2A, 0x02, 0x00, 0x10, 0x06, 0x03, 0x29, - 0x02, 0x00, 0x2A, 0x01, 0x86, 0x00, 0x0B, 0x06, 0x02, 0x6D, 0x2B, 0x02, - 0x00, 0x98, 0x2E, 0x0B, 0x06, 0x04, 0x01, 0x80, 0x46, 0xA3, 0x02, 0x01, - 0x06, 0x10, 0x95, 0x2E, 0x02, 0x00, 0x0D, 0x06, 0x05, 0x29, 0x95, 0x2E, - 0x04, 0x04, 0x01, 0x00, 0x03, 0x01, 0x2A, 0x95, 0x40, 0x2A, 0x96, 0x40, - 0x2A, 0x99, 0x40, 0x01, 0x86, 0x03, 0x11, 0x03, 0x08, 0x02, 0x02, 0x06, - 0x04, 0x01, 0x02, 0x8A, 0x42, 0x8A, 0x30, 0x05, 0x04, 0x01, 0x01, 0x8A, - 0x42, 0x02, 0x07, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x44, 0x29, 0x01, 0x82, - 0x01, 0x07, 0x01, 0xFC, 0x80, 0x00, 0x39, 0x82, 0x2F, 0x13, 0x2A, 0x82, - 0x41, 0x2A, 0x01, 0x81, 0x7F, 0x13, 0x5E, 0x37, 0x47, 0x01, 0x08, 0x12, - 0x5E, 0x01, 0x02, 0x13, 0x39, 0x01, 0x0C, 0x0C, 0x03, 0x09, 0x7E, 0x2F, - 0x43, 0x13, 0x2A, 0x7E, 0x41, 0x05, 0x04, 0x01, 0x00, 0x03, 0x09, 0x02, - 0x01, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x8F, 0x01, 0x20, 0x34, 0x01, 0x20, - 0x90, 0x42, 0x7B, 0x2A, 0x03, 0x05, 0x2A, 0x02, 0x04, 0x0B, 0x06, 0x80, - 0x49, 0x2A, 0x2E, 0x2A, 0x9C, 0x2A, 0x01, 0x0C, 0x12, 0x2A, 0x01, 0x01, - 0x0F, 0x47, 0x01, 0x02, 0x0F, 0x39, 0x06, 0x0A, 0x2A, 0x02, 0x09, 0x13, - 0x05, 0x04, 0x65, 0x01, 0x00, 0x2A, 0x02, 0x08, 0x05, 0x0E, 0x2A, 0x01, - 0x81, 0x70, 0x13, 0x01, 0x20, 0x0E, 0x06, 0x04, 0x65, 0x01, 0x00, 0x2A, - 0x2A, 0x06, 0x10, 0x02, 0x05, 0x63, 0x40, 0x02, 0x05, 0x40, 0x02, 0x05, - 0x01, 0x04, 0x08, 0x03, 0x05, 0x04, 0x01, 0x65, 0x01, 0x04, 0x08, 0x04, - 0xFF, 0x30, 0x29, 0x02, 0x05, 0x7B, 0x09, 0x01, 0x02, 0x12, 0x2A, 0x05, - 0x03, 0x01, 0x28, 0xA3, 0x7C, 0x42, 0x8C, 0x2E, 0x01, 0x83, 0xFF, 0x7F, - 0x0F, 0x06, 0x0D, 0x01, 0x03, 0xA4, 0x06, 0x04, 0x01, 0x80, 0x78, 0xA3, - 0x01, 0x00, 0x8C, 0x40, 0x18, 0x05, 0x03, 0x01, 0x28, 0xA3, 0x01, 0x00, - 0x00, 0x00, 0xB4, 0xB3, 0x00, 0x04, 0x78, 0x2E, 0xCE, 0x06, 0x16, 0xC0, - 0x2A, 0x01, 0x84, 0x00, 0x10, 0x06, 0x02, 0x6F, 0x2B, 0x2A, 0x03, 0x00, - 0x85, 0x47, 0xB6, 0x02, 0x00, 0x78, 0x2E, 0xA8, 0x27, 0x78, 0x2E, 0x2A, - 0xCC, 0x47, 0xCB, 0x03, 0x01, 0x03, 0x02, 0x02, 0x01, 0x02, 0x02, 0x39, - 0x06, 0x14, 0xC2, 0x2A, 0x03, 0x03, 0x85, 0x47, 0xB6, 0x02, 0x03, 0x78, - 0x2E, 0xA8, 0x02, 0x02, 0x06, 0x03, 0x26, 0x04, 0x01, 0x24, 0x9D, 0x00, - 0x00, 0xBA, 0x01, 0x10, 0x0F, 0x05, 0x02, 0x73, 0x2B, 0x00, 0x00, 0x9E, - 0xBA, 0x01, 0x14, 0x0E, 0x06, 0x02, 0x73, 0x2B, 0x85, 0x01, 0x0C, 0x08, - 0x01, 0x0C, 0xB6, 0x9D, 0x85, 0x2A, 0x01, 0x0C, 0x08, 0x01, 0x0C, 0x32, - 0x05, 0x02, 0x67, 0x2B, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x02, 0x00, - 0x9A, 0x02, 0x01, 0x02, 0x00, 0x3C, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02, - 0x65, 0x00, 0xD1, 0x04, 0x74, 0x00, 0xC0, 0x01, 0x01, 0x0E, 0x06, 0x02, - 0x68, 0x2B, 0xC2, 0x2A, 0x2A, 0x5F, 0x47, 0x01, 0x05, 0x11, 0x39, 0x06, - 0x02, 0x68, 0x2B, 0x01, 0x08, 0x08, 0x2A, 0x84, 0x30, 0x0B, 0x06, 0x0D, - 0x2A, 0x01, 0x01, 0x47, 0x0C, 0x3F, 0x2A, 0x84, 0x42, 0x86, 0x42, 0x04, - 0x01, 0x29, 0x00, 0x00, 0xC0, 0x8A, 0x30, 0x01, 0x00, 0x3A, 0x0F, 0x06, - 0x13, 0x29, 0x01, 0x01, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x06, 0x02, - 0x6B, 0x2B, 0x01, 0x02, 0x8A, 0x42, 0x04, 0x28, 0x01, 0x02, 0x3A, 0x0F, - 0x06, 0x1F, 0x29, 0x01, 0x0D, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0xC2, 0x01, - 0x0C, 0x0F, 0x05, 0x02, 0x6B, 0x2B, 0x85, 0x01, 0x0C, 0xB6, 0x8B, 0x85, - 0x01, 0x0C, 0x32, 0x05, 0x02, 0x6B, 0x2B, 0x04, 0x03, 0x6B, 0x2B, 0x29, - 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x2A, 0x06, 0x1D, 0xC2, 0x06, 0x03, - 0xBC, 0x04, 0x15, 0xC0, 0x2A, 0x01, 0x81, 0x7F, 0x0D, 0x06, 0x0C, 0x2A, - 0x8D, 0x08, 0x01, 0x00, 0x47, 0x42, 0x8D, 0x47, 0xB6, 0x04, 0x01, 0xC9, - 0x04, 0x60, 0x9D, 0x9D, 0x00, 0x00, 0xBB, 0x2A, 0x5F, 0x06, 0x07, 0x29, - 0x06, 0x02, 0x69, 0x2B, 0x04, 0x74, 0x00, 0x00, 0xC3, 0x01, 0x03, 0xC1, - 0x47, 0x29, 0x47, 0x00, 0x00, 0xC0, 0xC9, 0x00, 0x03, 0x01, 0x00, 0x03, - 0x00, 0xC0, 0xA7, 0x2A, 0x06, 0x80, 0x50, 0xC2, 0x03, 0x01, 0xC2, 0x03, - 0x02, 0x02, 0x01, 0x01, 0x08, 0x0F, 0x06, 0x16, 0x02, 0x02, 0x01, 0x0F, - 0x0D, 0x06, 0x0D, 0x01, 0x01, 0x02, 0x02, 0x01, 0x10, 0x08, 0x0C, 0x02, - 0x00, 0x39, 0x03, 0x00, 0x04, 0x2A, 0x02, 0x01, 0x01, 0x02, 0x11, 0x02, - 0x01, 0x01, 0x06, 0x0D, 0x13, 0x02, 0x02, 0x01, 0x01, 0x0F, 0x02, 0x02, - 0x01, 0x03, 0x0F, 0x39, 0x13, 0x06, 0x11, 0x02, 0x00, 0x01, 0x01, 0x02, - 0x02, 0x62, 0x01, 0x02, 0x0C, 0x02, 0x01, 0x08, 0x0C, 0x39, 0x03, 0x00, - 0x04, 0xFF, 0x2C, 0x9D, 0x02, 0x00, 0x00, 0x00, 0xC0, 0xA7, 0xBD, 0x82, - 0x41, 0x9D, 0x00, 0x00, 0xC0, 0xA7, 0xC0, 0xA7, 0x01, 0x00, 0x7E, 0x41, - 0x2A, 0x06, 0x15, 0xC0, 0x2A, 0x01, 0x20, 0x0B, 0x06, 0x0B, 0x01, 0x01, - 0x47, 0x0C, 0x7E, 0x2F, 0x39, 0x7E, 0x41, 0x04, 0x01, 0x29, 0x04, 0x68, - 0x9D, 0x9D, 0x00, 0x00, 0x01, 0x02, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3, - 0x08, 0x00, 0x00, 0x01, 0x03, 0x9A, 0xC3, 0x01, 0x08, 0x0C, 0xC3, 0x08, - 0x01, 0x08, 0x0C, 0xC3, 0x08, 0x00, 0x00, 0x01, 0x01, 0x9A, 0xC3, 0x00, - 0x00, 0x3D, 0x2A, 0x5D, 0x05, 0x01, 0x00, 0x29, 0xD1, 0x04, 0x76, 0x02, - 0x03, 0x00, 0x94, 0x30, 0x03, 0x01, 0x01, 0x00, 0x2A, 0x02, 0x01, 0x0B, - 0x06, 0x10, 0x2A, 0x01, 0x01, 0x0C, 0x93, 0x08, 0x2E, 0x02, 0x00, 0x0F, - 0x06, 0x01, 0x00, 0x61, 0x04, 0x6A, 0x29, 0x01, 0x7F, 0x00, 0x00, 0x2C, - 0x19, 0x38, 0x06, 0x04, 0xCF, 0x29, 0x04, 0x78, 0x01, 0x16, 0x89, 0x42, - 0x01, 0x00, 0xE2, 0x01, 0x00, 0xE1, 0x2C, 0x01, 0x17, 0x89, 0x42, 0x00, - 0x00, 0x01, 0x15, 0x89, 0x42, 0x47, 0x57, 0x29, 0x57, 0x29, 0x2C, 0x00, - 0x00, 0x01, 0x01, 0x47, 0xC6, 0x00, 0x00, 0xBB, 0x01, 0x01, 0x0F, 0x05, - 0x02, 0x73, 0x2B, 0x2A, 0xC9, 0x29, 0x00, 0x00, 0x47, 0x3A, 0x9A, 0x47, - 0x2A, 0x06, 0x05, 0xC3, 0x29, 0x62, 0x04, 0x78, 0x29, 0x00, 0x02, 0x03, - 0x00, 0x78, 0x2E, 0x9C, 0x03, 0x01, 0x02, 0x01, 0x01, 0x0F, 0x13, 0x02, - 0x01, 0x01, 0x04, 0x12, 0x01, 0x0F, 0x13, 0x02, 0x01, 0x01, 0x08, 0x12, - 0x01, 0x0F, 0x13, 0x01, 0x00, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x00, - 0x01, 0x18, 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x81, - 0x0D, 0x01, 0x01, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x10, - 0x02, 0x00, 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x77, 0x01, - 0x02, 0x3A, 0x0F, 0x06, 0x10, 0x29, 0x01, 0x01, 0x01, 0x20, 0x02, 0x00, - 0x06, 0x03, 0x4C, 0x04, 0x01, 0x4D, 0x04, 0x80, 0x61, 0x01, 0x03, 0x3A, - 0x0F, 0x06, 0x0F, 0x29, 0x29, 0x01, 0x10, 0x02, 0x00, 0x06, 0x03, 0x4A, - 0x04, 0x01, 0x4B, 0x04, 0x80, 0x4C, 0x01, 0x04, 0x3A, 0x0F, 0x06, 0x0E, - 0x29, 0x29, 0x01, 0x20, 0x02, 0x00, 0x06, 0x03, 0x4A, 0x04, 0x01, 0x4B, - 0x04, 0x38, 0x01, 0x05, 0x3A, 0x0F, 0x06, 0x0C, 0x29, 0x29, 0x02, 0x00, - 0x06, 0x03, 0x4E, 0x04, 0x01, 0x4F, 0x04, 0x26, 0x2A, 0x01, 0x09, 0x10, - 0x06, 0x02, 0x6A, 0x2B, 0x47, 0x29, 0x2A, 0x01, 0x01, 0x13, 0x01, 0x04, - 0x0C, 0x01, 0x10, 0x08, 0x47, 0x01, 0x08, 0x13, 0x01, 0x10, 0x47, 0x09, - 0x02, 0x00, 0x06, 0x03, 0x48, 0x04, 0x01, 0x49, 0x00, 0x29, 0x00, 0x00, - 0x9C, 0x01, 0x0C, 0x12, 0x01, 0x02, 0x10, 0x00, 0x00, 0x9C, 0x01, 0x0C, - 0x12, 0x2A, 0x60, 0x47, 0x01, 0x03, 0x0B, 0x13, 0x00, 0x00, 0x9C, 0x01, - 0x0C, 0x12, 0x01, 0x01, 0x0F, 0x00, 0x00, 0x9C, 0x01, 0x0C, 0x12, 0x5F, - 0x00, 0x00, 0x1B, 0x01, 0x00, 0x75, 0x30, 0x2A, 0x06, 0x22, 0x01, 0x01, - 0x3A, 0x0F, 0x06, 0x06, 0x29, 0x01, 0x00, 0xA0, 0x04, 0x14, 0x01, 0x02, - 0x3A, 0x0F, 0x06, 0x0D, 0x29, 0x77, 0x30, 0x01, 0x01, 0x0F, 0x06, 0x03, - 0x01, 0x10, 0x39, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x7D, 0x30, 0x05, - 0x33, 0x31, 0x06, 0x30, 0x88, 0x30, 0x01, 0x14, 0x3A, 0x0F, 0x06, 0x06, - 0x29, 0x01, 0x02, 0x39, 0x04, 0x22, 0x01, 0x15, 0x3A, 0x0F, 0x06, 0x09, - 0x29, 0xAA, 0x06, 0x03, 0x01, 0x7F, 0xA0, 0x04, 0x13, 0x01, 0x16, 0x3A, - 0x0F, 0x06, 0x06, 0x29, 0x01, 0x01, 0x39, 0x04, 0x07, 0x29, 0x01, 0x04, - 0x39, 0x01, 0x00, 0x29, 0x19, 0x06, 0x03, 0x01, 0x08, 0x39, 0x00, 0x00, - 0x1B, 0x2A, 0x05, 0x13, 0x31, 0x06, 0x10, 0x88, 0x30, 0x01, 0x15, 0x0F, - 0x06, 0x08, 0x29, 0xAA, 0x01, 0x00, 0x77, 0x42, 0x04, 0x01, 0x23, 0x00, - 0x00, 0xCF, 0x01, 0x07, 0x13, 0x01, 0x01, 0x10, 0x06, 0x02, 0x73, 0x2B, - 0x00, 0x01, 0x03, 0x00, 0x2C, 0x19, 0x06, 0x05, 0x02, 0x00, 0x89, 0x42, - 0x00, 0xCF, 0x29, 0x04, 0x74, 0x00, 0x01, 0x14, 0xD2, 0x01, 0x01, 0xE2, - 0x2C, 0x2A, 0x01, 0x00, 0xCA, 0x01, 0x16, 0xD2, 0xD6, 0x2C, 0x00, 0x00, - 0x01, 0x0B, 0xE2, 0x52, 0x2A, 0x2A, 0x01, 0x03, 0x08, 0xE1, 0xE1, 0x14, - 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE1, 0x1E, 0x2A, 0x06, 0x05, 0x85, - 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x01, 0x00, 0xDC, 0x95, - 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, 0x05, 0x63, 0x01, 0x00, 0xDD, 0x08, - 0x50, 0x08, 0x01, 0x03, 0x08, 0x01, 0x0D, 0xE2, 0xE1, 0x01, 0x00, 0xDC, - 0xE2, 0x01, 0x01, 0xDC, 0x29, 0x95, 0x2E, 0x01, 0x86, 0x03, 0x11, 0x06, - 0x08, 0x01, 0x00, 0xDD, 0xE0, 0x01, 0x01, 0xDD, 0x29, 0x50, 0xE0, 0x16, - 0x15, 0x2A, 0x5D, 0x06, 0x02, 0x29, 0x00, 0xE0, 0x1F, 0x2A, 0x06, 0x05, - 0x85, 0x47, 0xDA, 0x04, 0x77, 0x29, 0x04, 0x6C, 0x00, 0x9E, 0x01, 0x14, - 0xE2, 0x01, 0x0C, 0xE1, 0x85, 0x01, 0x0C, 0xDA, 0x00, 0x04, 0x03, 0x00, - 0x01, 0x02, 0xE2, 0x01, 0x80, 0x46, 0x8A, 0x30, 0x01, 0x02, 0x0F, 0x06, - 0x0C, 0x02, 0x00, 0x06, 0x04, 0x01, 0x05, 0x04, 0x02, 0x01, 0x1D, 0x04, - 0x02, 0x01, 0x00, 0x03, 0x01, 0x86, 0x30, 0x06, 0x04, 0x01, 0x05, 0x04, - 0x02, 0x01, 0x00, 0x03, 0x02, 0x8C, 0x2E, 0x2A, 0x06, 0x05, 0x62, 0x21, - 0x01, 0x07, 0x08, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03, - 0x08, 0x2A, 0x06, 0x03, 0x01, 0x02, 0x08, 0x08, 0xE1, 0x95, 0x2E, 0xE0, - 0x8E, 0x01, 0x04, 0x17, 0x8E, 0x01, 0x04, 0x08, 0x01, 0x1C, 0x34, 0x8E, - 0x01, 0x20, 0xDA, 0x01, 0x20, 0xE2, 0x8F, 0x01, 0x20, 0xDA, 0x78, 0x2E, - 0xE0, 0x01, 0x00, 0xE2, 0x02, 0x01, 0x02, 0x02, 0x08, 0x02, 0x03, 0x08, - 0x2A, 0x06, 0x80, 0x40, 0xE0, 0x02, 0x01, 0x2A, 0x06, 0x10, 0x01, 0x83, - 0xFE, 0x01, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x62, 0x8B, 0x47, 0xDB, - 0x04, 0x01, 0x29, 0x02, 0x02, 0x06, 0x0C, 0x01, 0x01, 0xE0, 0x01, 0x01, - 0xE0, 0x86, 0x30, 0x01, 0x08, 0x09, 0xE2, 0x02, 0x03, 0x2A, 0x06, 0x11, - 0x01, 0x10, 0xE0, 0x01, 0x04, 0x09, 0x2A, 0xE0, 0x64, 0x2A, 0xE0, 0x62, - 0x85, 0x47, 0xDB, 0x04, 0x01, 0x29, 0x04, 0x01, 0x29, 0x00, 0x00, 0x01, - 0x0E, 0xE2, 0x01, 0x00, 0xE1, 0x00, 0x03, 0x78, 0x2E, 0xCC, 0x05, 0x01, - 0x00, 0x7E, 0x2F, 0x2A, 0x01, 0x82, 0x80, 0x80, 0x80, 0x00, 0x13, 0x06, - 0x05, 0x29, 0x01, 0x1D, 0x04, 0x0E, 0x2A, 0x01, 0x83, 0xC0, 0x80, 0x80, - 0x00, 0x13, 0x2A, 0x06, 0x01, 0x47, 0x29, 0xA5, 0x03, 0x00, 0x02, 0x00, - 0x25, 0x2A, 0x5D, 0x06, 0x02, 0x37, 0x2B, 0x03, 0x01, 0x95, 0x2E, 0x01, - 0x86, 0x03, 0x11, 0x03, 0x02, 0x01, 0x0C, 0xE2, 0x02, 0x01, 0x80, 0x30, - 0x08, 0x02, 0x02, 0x01, 0x02, 0x13, 0x08, 0x01, 0x06, 0x08, 0xE1, 0x01, - 0x03, 0xE2, 0x02, 0x00, 0xE0, 0x7F, 0x80, 0x30, 0xDB, 0x02, 0x02, 0x06, - 0x1C, 0x92, 0x2E, 0x2A, 0x01, 0x83, 0xFE, 0x00, 0x0B, 0x06, 0x03, 0xE0, - 0x04, 0x0F, 0x01, 0x81, 0x7F, 0x13, 0xE2, 0x78, 0x2E, 0xCD, 0x01, 0x01, - 0x0C, 0x01, 0x03, 0x08, 0xE2, 0x02, 0x01, 0xE0, 0x85, 0x02, 0x01, 0xDA, - 0x00, 0x00, 0x56, 0x2A, 0x01, 0x00, 0x0F, 0x06, 0x02, 0x65, 0x00, 0xCF, - 0x29, 0x04, 0x73, 0x00, 0x2A, 0xE2, 0xDA, 0x00, 0x00, 0x01, 0x00, 0x78, - 0x2E, 0xCB, 0x06, 0x0C, 0x63, 0x3A, 0x06, 0x08, 0x01, 0x80, 0x41, 0xE2, - 0x01, 0x80, 0x42, 0xE2, 0x46, 0x06, 0x07, 0x61, 0x3A, 0x06, 0x03, 0x01, - 0x01, 0xE2, 0x45, 0x06, 0x08, 0x61, 0x3A, 0x06, 0x04, 0x01, 0x80, 0x40, - 0xE2, 0x47, 0x29, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x46, 0x45, 0x39, - 0x05, 0x14, 0x01, 0x01, 0x01, 0x80, 0x7C, 0xDE, 0x03, 0x00, 0x01, 0x03, - 0x01, 0x80, 0x7C, 0xDE, 0x02, 0x00, 0x08, 0x47, 0x29, 0x00, 0x46, 0x06, - 0x07, 0x01, 0x01, 0x44, 0x29, 0xDE, 0x03, 0x00, 0x45, 0x06, 0x0A, 0x01, - 0x03, 0x44, 0x29, 0xDE, 0x02, 0x00, 0x08, 0x03, 0x00, 0x29, 0x02, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x01, 0x04, 0xDF, 0x01, 0x05, 0xDF, 0x01, 0x06, - 0xDF, 0x01, 0x03, 0xDF, 0x01, 0x02, 0xDF, 0x0A, 0x65, 0x00, 0x01, 0x03, - 0x00, 0x3A, 0x01, 0x01, 0x02, 0x00, 0x0C, 0x13, 0x05, 0x01, 0x00, 0x63, - 0x01, 0x03, 0x3B, 0x06, 0x07, 0x02, 0x00, 0xE2, 0x01, 0x02, 0x3B, 0xE2, - 0x00, 0x00, 0x2A, 0x01, 0x08, 0x54, 0xE2, 0xE2, 0x00, 0x00, 0x2A, 0x01, - 0x10, 0x54, 0xE2, 0xE0, 0x00, 0x00, 0x2A, 0x57, 0x06, 0x02, 0x29, 0x00, - 0xCF, 0x29, 0x04, 0x76 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 15, - 20, - 25, - 30, - 35, - 40, - 44, - 48, - 52, - 56, - 60, - 64, - 68, - 72, - 76, - 80, - 84, - 88, - 92, - 96, - 100, - 104, - 109, - 114, - 119, - 124, - 129, - 134, - 139, - 144, - 149, - 154, - 159, - 164, - 169, - 174, - 180, - 185, - 190, - 195, - 200, - 205, - 210, - 215, - 220, - 225, - 230, - 235, - 240, - 245, - 250, - 255, - 260, - 265, - 270, - 275, - 280, - 285, - 290, - 299, - 303, - 328, - 334, - 353, - 364, - 405, - 516, - 520, - 553, - 563, - 587, - 669, - 683, - 689, - 748, - 767, - 789, - 838, - 887, - 963, - 1065, - 1076, - 1670, - 1674, - 1741, - 1751, - 1782, - 1806, - 1852, - 1922, - 1962, - 1976, - 1985, - 1989, - 2084, - 2092, - 2128, - 2139, - 2155, - 2161, - 2172, - 2207, - 2233, - 2245, - 2251, - 2264, - 2279, - 2472, - 2481, - 2494, - 2503, - 2510, - 2616, - 2641, - 2654, - 2670, - 2688, - 2720, - 2793, - 2806, - 2987, - 2995, - 3122, - 3136, - 3141, - 3185, - 3242, - 3263, - 3290, - 3298, - 3306 -}; - -#define T0_INTERPRETED 93 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_ssl_hs_server_init_main, 166) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_ssl_hs_server_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* * */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a * b); - - } - break; - case 8: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 9: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 10: { - /* -rot */ - T0_NROT(); - } - break; - case 11: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 12: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 13: { - /* <= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a <= b)); - - } - break; - case 14: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 15: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 16: { - /* > */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a > b)); - - } - break; - case 17: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 18: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 19: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 20: { - /* begin-cert */ - - if (ENG->chain_len == 0) { - T0_PUSHi(-1); - } else { - ENG->cert_cur = ENG->chain->data; - ENG->cert_len = ENG->chain->data_len; - ENG->chain ++; - ENG->chain_len --; - T0_PUSH(ENG->cert_len); - } - - } - break; - case 21: { - /* begin-ta-name */ - - const br_x500_name *dn; - if (CTX->cur_dn_index >= CTX->num_tas) { - T0_PUSHi(-1); - } else { - if (CTX->ta_names == NULL) { - dn = &CTX->tas[CTX->cur_dn_index].dn; - } else { - dn = &CTX->ta_names[CTX->cur_dn_index]; - } - CTX->cur_dn_index ++; - CTX->cur_dn = dn->data; - CTX->cur_dn_len = dn->len; - T0_PUSH(CTX->cur_dn_len); - } - - } - break; - case 22: { - /* begin-ta-name-list */ - - CTX->cur_dn_index = 0; - - } - break; - case 23: { - /* bzero */ - - size_t len = (size_t)T0_POP(); - void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - memset(addr, 0, len); - - } - break; - case 24: { - /* call-policy-handler */ - - int x; - br_ssl_server_choices choices; - - x = (*CTX->policy_vtable)->choose( - CTX->policy_vtable, CTX, &choices); - ENG->session.cipher_suite = choices.cipher_suite; - CTX->sign_hash_id = choices.algo_id; - ENG->chain = choices.chain; - ENG->chain_len = choices.chain_len; - T0_PUSHi(-(x != 0)); - - } - break; - case 25: { - /* can-output? */ - - T0_PUSHi(-(ENG->hlen_out > 0)); - - } - break; - case 26: { - /* check-resume */ - - if (ENG->session.session_id_len == 32 - && CTX->cache_vtable != NULL && (*CTX->cache_vtable)->load( - CTX->cache_vtable, CTX, &ENG->session)) - { - T0_PUSHi(-1); - } else { - T0_PUSH(0); - } - - } - break; - case 27: { - /* co */ - T0_CO(); - } - break; - case 28: { - /* compute-Finished-inner */ - - int prf_id = T0_POP(); - int from_client = T0_POPi(); - unsigned char tmp[48]; - br_tls_prf_seed_chunk seed; - - br_tls_prf_impl prf = br_ssl_engine_get_PRF(ENG, prf_id); - seed.data = tmp; - if (ENG->session.version >= BR_TLS12) { - seed.len = br_multihash_out(&ENG->mhash, prf_id, tmp); - } else { - br_multihash_out(&ENG->mhash, br_md5_ID, tmp); - br_multihash_out(&ENG->mhash, br_sha1_ID, tmp + 16); - seed.len = 36; - } - prf(ENG->pad, 12, ENG->session.master_secret, - sizeof ENG->session.master_secret, - from_client ? "client finished" : "server finished", - 1, &seed); - - } - break; - case 29: { - /* compute-hash-CV */ - - int i; - - for (i = 1; i <= 6; i ++) { - br_multihash_out(&ENG->mhash, i, - ENG->pad + HASH_PAD_OFF[i - 1]); - } - - } - break; - case 30: { - /* copy-cert-chunk */ - - size_t clen; - - clen = ENG->cert_len; - if (clen > sizeof ENG->pad) { - clen = sizeof ENG->pad; - } - memcpy(ENG->pad, ENG->cert_cur, clen); - ENG->cert_cur += clen; - ENG->cert_len -= clen; - T0_PUSH(clen); - - } - break; - case 31: { - /* copy-dn-chunk */ - - size_t clen; - - clen = CTX->cur_dn_len; - if (clen > sizeof ENG->pad) { - clen = sizeof ENG->pad; - } - memcpy(ENG->pad, CTX->cur_dn, clen); - CTX->cur_dn += clen; - CTX->cur_dn_len -= clen; - T0_PUSH(clen); - - } - break; - case 32: { - /* copy-hash-CV */ - - int id = T0_POP(); - size_t off, len; - - if (id == 0) { - off = 0; - len = 36; - } else { - if (br_multihash_getimpl(&ENG->mhash, id) == 0) { - T0_PUSH(0); - T0_RET(); - } - off = HASH_PAD_OFF[id - 1]; - len = HASH_PAD_OFF[id] - off; - } - memcpy(CTX->hash_CV, ENG->pad + off, len); - CTX->hash_CV_len = len; - CTX->hash_CV_id = id; - T0_PUSHi(-1); - - } - break; - case 33: { - /* copy-protocol-name */ - - size_t idx = T0_POP(); - size_t len = strlen(ENG->protocol_names[idx]); - memcpy(ENG->pad, ENG->protocol_names[idx], len); - T0_PUSH(len); - - } - break; - case 34: { - /* data-get8 */ - - size_t addr = T0_POP(); - T0_PUSH(t0_datablock[addr]); - - } - break; - case 35: { - /* discard-input */ - - ENG->hlen_in = 0; - - } - break; - case 36: { - /* do-ecdh */ - - int prf_id = T0_POPi(); - size_t len = T0_POP(); - do_ecdh(CTX, prf_id, ENG->pad, len); - - } - break; - case 37: { - /* do-ecdhe-part1 */ - - int curve = T0_POPi(); - T0_PUSHi(do_ecdhe_part1(CTX, curve)); - - } - break; - case 38: { - /* do-ecdhe-part2 */ - - int prf_id = T0_POPi(); - size_t len = T0_POP(); - do_ecdhe_part2(CTX, prf_id, ENG->pad, len); - - } - break; - case 39: { - /* do-rsa-decrypt */ - - int prf_id = T0_POPi(); - size_t len = T0_POP(); - do_rsa_decrypt(CTX, prf_id, ENG->pad, len); - - } - break; - case 40: { - /* do-static-ecdh */ - - do_static_ecdh(CTX, T0_POP()); - - } - break; - case 41: { - /* drop */ - (void)T0_POP(); - } - break; - case 42: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 43: { - /* fail */ - - br_ssl_engine_fail(ENG, (int)T0_POPi()); - T0_CO(); - - } - break; - case 44: { - /* flush-record */ - - br_ssl_engine_flush_record(ENG); - - } - break; - case 45: { - /* get-key-type-usages */ - - const br_x509_class *xc; - const br_x509_pkey *pk; - unsigned usages; - - xc = *(ENG->x509ctx); - pk = xc->get_pkey(ENG->x509ctx, &usages); - if (pk == NULL) { - T0_PUSH(0); - } else { - T0_PUSH(pk->key_type | usages); - } - - } - break; - case 46: { - /* get16 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*(uint16_t *)(void *)((unsigned char *)ENG + addr)); - - } - break; - case 47: { - /* get32 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*(uint32_t *)(void *)((unsigned char *)ENG + addr)); - - } - break; - case 48: { - /* get8 */ - - size_t addr = (size_t)T0_POP(); - T0_PUSH(*((unsigned char *)ENG + addr)); - - } - break; - case 49: { - /* has-input? */ - - T0_PUSHi(-(ENG->hlen_in != 0)); - - } - break; - case 50: { - /* memcmp */ - - size_t len = (size_t)T0_POP(); - void *addr2 = (unsigned char *)ENG + (size_t)T0_POP(); - void *addr1 = (unsigned char *)ENG + (size_t)T0_POP(); - int x = memcmp(addr1, addr2, len); - T0_PUSH((uint32_t)-(x == 0)); - - } - break; - case 51: { - /* memcpy */ - - size_t len = (size_t)T0_POP(); - void *src = (unsigned char *)ENG + (size_t)T0_POP(); - void *dst = (unsigned char *)ENG + (size_t)T0_POP(); - memcpy(dst, src, len); - - } - break; - case 52: { - /* mkrand */ - - size_t len = (size_t)T0_POP(); - void *addr = (unsigned char *)ENG + (size_t)T0_POP(); - br_hmac_drbg_generate(&ENG->rng, addr, len); - - } - break; - case 53: { - /* more-incoming-bytes? */ - - T0_PUSHi(ENG->hlen_in != 0 || !br_ssl_engine_recvrec_finished(ENG)); - - } - break; - case 54: { - /* multihash-init */ - - br_multihash_init(&ENG->mhash); - - } - break; - case 55: { - /* neg */ - - uint32_t a = T0_POP(); - T0_PUSH(-a); - - } - break; - case 56: { - /* not */ - - uint32_t a = T0_POP(); - T0_PUSH(~a); - - } - break; - case 57: { - /* or */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a | b); - - } - break; - case 58: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 59: { - /* pick */ - T0_PICK(T0_POP()); - } - break; - case 60: { - /* read-chunk-native */ - - size_t clen = ENG->hlen_in; - if (clen > 0) { - uint32_t addr, len; - - len = T0_POP(); - addr = T0_POP(); - if ((size_t)len < clen) { - clen = (size_t)len; - } - memcpy((unsigned char *)ENG + addr, ENG->hbuf_in, clen); - if (ENG->record_type_in == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, ENG->hbuf_in, clen); - } - T0_PUSH(addr + (uint32_t)clen); - T0_PUSH(len - (uint32_t)clen); - ENG->hbuf_in += clen; - ENG->hlen_in -= clen; - } - - } - break; - case 61: { - /* read8-native */ - - if (ENG->hlen_in > 0) { - unsigned char x; - - x = *ENG->hbuf_in ++; - if (ENG->record_type_in == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, &x, 1); - } - T0_PUSH(x); - ENG->hlen_in --; - } else { - T0_PUSHi(-1); - } - - } - break; - case 62: { - /* save-session */ - - if (CTX->cache_vtable != NULL) { - (*CTX->cache_vtable)->save( - CTX->cache_vtable, CTX, &ENG->session); - } - - } - break; - case 63: { - /* set-max-frag-len */ - - size_t max_frag_len = T0_POP(); - - br_ssl_engine_new_max_frag_len(ENG, max_frag_len); - - /* - * We must adjust our own output limit. Since we call this only - * after receiving a ClientHello and before beginning to send - * the ServerHello, the next output record should be empty at - * that point, so we can use max_frag_len as a limit. - */ - if (ENG->hlen_out > max_frag_len) { - ENG->hlen_out = max_frag_len; - } - - } - break; - case 64: { - /* set16 */ - - size_t addr = (size_t)T0_POP(); - *(uint16_t *)(void *)((unsigned char *)ENG + addr) = (uint16_t)T0_POP(); - - } - break; - case 65: { - /* set32 */ - - size_t addr = (size_t)T0_POP(); - *(uint32_t *)(void *)((unsigned char *)ENG + addr) = (uint32_t)T0_POP(); - - } - break; - case 66: { - /* set8 */ - - size_t addr = (size_t)T0_POP(); - *((unsigned char *)ENG + addr) = (unsigned char)T0_POP(); - - } - break; - case 67: { - /* supported-curves */ - - uint32_t x = ENG->iec == NULL ? 0 : ENG->iec->supported_curves; - T0_PUSH(x); - - } - break; - case 68: { - /* supported-hash-functions */ - - int i; - unsigned x, num; - - x = 0; - num = 0; - for (i = br_sha1_ID; i <= br_sha512_ID; i ++) { - if (br_multihash_getimpl(&ENG->mhash, i)) { - x |= 1U << i; - num ++; - } - } - T0_PUSH(x); - T0_PUSH(num); - - } - break; - case 69: { - /* supports-ecdsa? */ - - T0_PUSHi(-(ENG->iecdsa != 0)); - - } - break; - case 70: { - /* supports-rsa-sign? */ - - T0_PUSHi(-(ENG->irsavrfy != 0)); - - } - break; - case 71: { - /* swap */ - T0_SWAP(); - } - break; - case 72: { - /* switch-aesccm-in */ - - int is_client, prf_id; - unsigned cipher_key_len, tag_len; - - tag_len = T0_POP(); - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_ccm_in(ENG, is_client, prf_id, - ENG->iaes_ctrcbc, cipher_key_len, tag_len); - - } - break; - case 73: { - /* switch-aesccm-out */ - - int is_client, prf_id; - unsigned cipher_key_len, tag_len; - - tag_len = T0_POP(); - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_ccm_out(ENG, is_client, prf_id, - ENG->iaes_ctrcbc, cipher_key_len, tag_len); - - } - break; - case 74: { - /* switch-aesgcm-in */ - - int is_client, prf_id; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_gcm_in(ENG, is_client, prf_id, - ENG->iaes_ctr, cipher_key_len); - - } - break; - case 75: { - /* switch-aesgcm-out */ - - int is_client, prf_id; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_gcm_out(ENG, is_client, prf_id, - ENG->iaes_ctr, cipher_key_len); - - } - break; - case 76: { - /* switch-cbc-in */ - - int is_client, prf_id, mac_id, aes; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - aes = T0_POP(); - mac_id = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_cbc_in(ENG, is_client, prf_id, mac_id, - aes ? ENG->iaes_cbcdec : ENG->ides_cbcdec, cipher_key_len); - - } - break; - case 77: { - /* switch-cbc-out */ - - int is_client, prf_id, mac_id, aes; - unsigned cipher_key_len; - - cipher_key_len = T0_POP(); - aes = T0_POP(); - mac_id = T0_POP(); - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_cbc_out(ENG, is_client, prf_id, mac_id, - aes ? ENG->iaes_cbcenc : ENG->ides_cbcenc, cipher_key_len); - - } - break; - case 78: { - /* switch-chapol-in */ - - int is_client, prf_id; - - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id); - - } - break; - case 79: { - /* switch-chapol-out */ - - int is_client, prf_id; - - prf_id = T0_POP(); - is_client = T0_POP(); - br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id); - - } - break; - case 80: { - /* ta-names-total-length */ - - size_t u, len; - - len = 0; - if (CTX->ta_names != NULL) { - for (u = 0; u < CTX->num_tas; u ++) { - len += CTX->ta_names[u].len + 2; - } - } else if (CTX->tas != NULL) { - for (u = 0; u < CTX->num_tas; u ++) { - len += CTX->tas[u].dn.len + 2; - } - } - T0_PUSH(len); - - } - break; - case 81: { - /* test-protocol-name */ - - size_t len = T0_POP(); - size_t u; - - for (u = 0; u < ENG->protocol_names_num; u ++) { - const char *name; - - name = ENG->protocol_names[u]; - if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) { - T0_PUSH(u); - T0_RET(); - } - } - T0_PUSHi(-1); - - } - break; - case 82: { - /* total-chain-length */ - - size_t u; - uint32_t total; - - total = 0; - for (u = 0; u < ENG->chain_len; u ++) { - total += 3 + (uint32_t)ENG->chain[u].data_len; - } - T0_PUSH(total); - - } - break; - case 83: { - /* u< */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 84: { - /* u>> */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x >> c); - - } - break; - case 85: { - /* verify-CV-sig */ - - int err; - - err = verify_CV_sig(CTX, T0_POP()); - T0_PUSHi(err); - - } - break; - case 86: { - /* write-blob-chunk */ - - size_t clen = ENG->hlen_out; - if (clen > 0) { - uint32_t addr, len; - - len = T0_POP(); - addr = T0_POP(); - if ((size_t)len < clen) { - clen = (size_t)len; - } - memcpy(ENG->hbuf_out, (unsigned char *)ENG + addr, clen); - if (ENG->record_type_out == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, ENG->hbuf_out, clen); - } - T0_PUSH(addr + (uint32_t)clen); - T0_PUSH(len - (uint32_t)clen); - ENG->hbuf_out += clen; - ENG->hlen_out -= clen; - } - - } - break; - case 87: { - /* write8-native */ - - unsigned char x; - - x = (unsigned char)T0_POP(); - if (ENG->hlen_out > 0) { - if (ENG->record_type_out == BR_SSL_HANDSHAKE) { - br_multihash_update(&ENG->mhash, &x, 1); - } - *ENG->hbuf_out ++ = x; - ENG->hlen_out --; - T0_PUSHi(-1); - } else { - T0_PUSHi(0); - } - - } - break; - case 88: { - /* x509-append */ - - const br_x509_class *xc; - size_t len; - - xc = *(ENG->x509ctx); - len = T0_POP(); - xc->append(ENG->x509ctx, ENG->pad, len); - - } - break; - case 89: { - /* x509-end-cert */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - xc->end_cert(ENG->x509ctx); - - } - break; - case 90: { - /* x509-end-chain */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - T0_PUSH(xc->end_chain(ENG->x509ctx)); - - } - break; - case 91: { - /* x509-start-cert */ - - const br_x509_class *xc; - - xc = *(ENG->x509ctx); - xc->start_cert(ENG->x509ctx, T0_POP()); - - } - break; - case 92: { - /* x509-start-chain */ - - const br_x509_class *xc; - uint32_t bc; - - bc = T0_POP(); - xc = *(ENG->x509ctx); - xc->start_chain(ENG->x509ctx, bc ? ENG->server_name : NULL); - - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_io.c b/src/tls/bearssl/ssl_io.c deleted file mode 100644 index 2a1a928e0..000000000 --- a/src/tls/bearssl/ssl_io.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_sslio_init(br_sslio_context *ctx, - br_ssl_engine_context *engine, - int (*low_read)(void *read_context, - unsigned char *data, size_t len), - void *read_context, - int (*low_write)(void *write_context, - const unsigned char *data, size_t len), - void *write_context) -{ - ctx->engine = engine; - ctx->low_read = low_read; - ctx->read_context = read_context; - ctx->low_write = low_write; - ctx->write_context = write_context; -} - -/* - * Run the engine, until the specified target state is achieved, or - * an error occurs. The target state is SENDAPP, RECVAPP, or the - * combination of both (the combination matches either). When a match is - * achieved, this function returns 0. On error, it returns -1. - */ -static int -run_until(br_sslio_context *ctx, unsigned target) -{ - for (;;) { - unsigned state; - - state = br_ssl_engine_current_state(ctx->engine); - if (state & BR_SSL_CLOSED) { - return -1; - } - - /* - * If there is some record data to send, do it. This takes - * precedence over everything else. - */ - if (state & BR_SSL_SENDREC) { - unsigned char *buf; - size_t len; - int wlen; - - buf = br_ssl_engine_sendrec_buf(ctx->engine, &len); - wlen = ctx->low_write(ctx->write_context, buf, len); - if (wlen < 0) { - /* - * If we received a close_notify and we - * still send something, then we have our - * own response close_notify to send, and - * the peer is allowed by RFC 5246 not to - * wait for it. - */ - if (!ctx->engine->shutdown_recv) { - br_ssl_engine_fail( - ctx->engine, BR_ERR_IO); - } - return -1; - } - if (wlen > 0) { - br_ssl_engine_sendrec_ack(ctx->engine, wlen); - } - continue; - } - - /* - * If we reached our target, then we are finished. - */ - if (state & target) { - return 0; - } - - /* - * If some application data must be read, and we did not - * exit, then this means that we are trying to write data, - * and that's not possible until the application data is - * read. This may happen if using a shared in/out buffer, - * and the underlying protocol is not strictly half-duplex. - * This is unrecoverable here, so we report an error. - */ - if (state & BR_SSL_RECVAPP) { - return -1; - } - - /* - * If we reached that point, then either we are trying - * to read data and there is some, or the engine is stuck - * until a new record is obtained. - */ - if (state & BR_SSL_RECVREC) { - unsigned char *buf; - size_t len; - int rlen; - - buf = br_ssl_engine_recvrec_buf(ctx->engine, &len); - rlen = ctx->low_read(ctx->read_context, buf, len); - if (rlen < 0) { - br_ssl_engine_fail(ctx->engine, BR_ERR_IO); - return -1; - } - if (rlen > 0) { - br_ssl_engine_recvrec_ack(ctx->engine, rlen); - } - continue; - } - - /* - * We can reach that point if the target RECVAPP, and - * the state contains SENDAPP only. This may happen with - * a shared in/out buffer. In that case, we must flush - * the buffered data to "make room" for a new incoming - * record. - */ - br_ssl_engine_flush(ctx->engine, 0); - } -} - -/* see bearssl_ssl.h */ -int -br_sslio_read(br_sslio_context *ctx, void *dst, size_t len) -{ - unsigned char *buf; - size_t alen; - - if (len == 0) { - return 0; - } - if (run_until(ctx, BR_SSL_RECVAPP) < 0) { - return -1; - } - buf = br_ssl_engine_recvapp_buf(ctx->engine, &alen); - if (alen > len) { - alen = len; - } - memcpy(dst, buf, alen); - br_ssl_engine_recvapp_ack(ctx->engine, alen); - return (int)alen; -} - -/* see bearssl_ssl.h */ -int -br_sslio_read_all(br_sslio_context *ctx, void *dst, size_t len) -{ - unsigned char *buf; - - buf = dst; - while (len > 0) { - int rlen; - - rlen = br_sslio_read(ctx, buf, len); - if (rlen < 0) { - return -1; - } - buf += rlen; - len -= (size_t)rlen; - } - return 0; -} - -#ifdef ARDUINO -int br_sslio_read_available(br_sslio_context *ctx) -{ - size_t alen; - unsigned state = br_ssl_engine_current_state(ctx->engine); - - if (state & BR_SSL_RECVREC) { - unsigned char *buf; - size_t len; - int rlen; - - buf = br_ssl_engine_recvrec_buf(ctx->engine, &len); - rlen = ctx->low_read(ctx->read_context, buf, len); - if (rlen < 0) { - br_ssl_engine_fail(ctx->engine, BR_ERR_IO); - return -1; - } - if (rlen > 0) { - br_ssl_engine_recvrec_ack(ctx->engine, rlen); - } - } - br_ssl_engine_recvapp_buf(ctx->engine, &alen); - return (int)alen; -} - -int br_sslio_peek(br_sslio_context *ctx, void *dst, size_t len) -{ - unsigned char *buf; - size_t alen; - - if (len == 0) { - return 0; - } - unsigned state = br_ssl_engine_current_state(ctx->engine); - - if (state & BR_SSL_RECVREC) { - unsigned char *buf; - size_t len; - int rlen; - - buf = br_ssl_engine_recvrec_buf(ctx->engine, &len); - rlen = ctx->low_read(ctx->read_context, buf, len); - if (rlen < 0) { - br_ssl_engine_fail(ctx->engine, BR_ERR_IO); - return -1; - } - if (rlen > 0) { - br_ssl_engine_recvrec_ack(ctx->engine, rlen); - } - } - buf = br_ssl_engine_recvapp_buf(ctx->engine, &alen); - if (alen > len) { - alen = len; - } - memcpy(dst, buf, alen); - return (int)alen; -} -#endif - -/* see bearssl_ssl.h */ -int -br_sslio_write(br_sslio_context *ctx, const void *src, size_t len) -{ - unsigned char *buf; - size_t alen; - - if (len == 0) { - return 0; - } - if (run_until(ctx, BR_SSL_SENDAPP) < 0) { - return -1; - } - buf = br_ssl_engine_sendapp_buf(ctx->engine, &alen); - if (alen > len) { - alen = len; - } - memcpy(buf, src, alen); - br_ssl_engine_sendapp_ack(ctx->engine, alen); - return (int)alen; -} - -/* see bearssl_ssl.h */ -int -br_sslio_write_all(br_sslio_context *ctx, const void *src, size_t len) -{ - const unsigned char *buf; - - buf = src; - while (len > 0) { - int wlen; - - wlen = br_sslio_write(ctx, buf, len); - if (wlen < 0) { - return -1; - } - buf += wlen; - len -= (size_t)wlen; - } - return 0; -} - -/* see bearssl_ssl.h */ -int -br_sslio_flush(br_sslio_context *ctx) -{ - /* - * We trigger a flush. We know the data is gone when there is - * no longer any record data to send, and we can either read - * or write application data. The call to run_until() does the - * job because it ensures that any assembled record data is - * first sent down the wire before considering anything else. - */ - br_ssl_engine_flush(ctx->engine, 0); - return run_until(ctx, BR_SSL_SENDAPP | BR_SSL_RECVAPP); -} - -/* see bearssl_ssl.h */ -int -br_sslio_close(br_sslio_context *ctx) -{ - br_ssl_engine_close(ctx->engine); - while (br_ssl_engine_current_state(ctx->engine) != BR_SSL_CLOSED) { - /* - * Discard any incoming application data. - */ - size_t len; - - run_until(ctx, BR_SSL_RECVAPP); - if (br_ssl_engine_recvapp_buf(ctx->engine, &len) != NULL) { - br_ssl_engine_recvapp_ack(ctx->engine, len); - } - } - return br_ssl_engine_last_error(ctx->engine) == BR_ERR_OK; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_keyexport.c b/src/tls/bearssl/ssl_keyexport.c deleted file mode 100644 index d5e7af489..000000000 --- a/src/tls/bearssl/ssl_keyexport.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Supported cipher suites that use SHA-384 for the PRF when selected - * for TLS 1.2. All other cipher suites are deemed to use SHA-256. - */ -static const uint16_t suites_sha384[] = { - BR_TLS_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 -}; - -/* see bearssl_ssl.h */ -int -br_ssl_key_export(br_ssl_engine_context *cc, - void *dst, size_t len, const char *label, - const void *context, size_t context_len) -{ - br_tls_prf_seed_chunk chunks[4]; - br_tls_prf_impl iprf; - size_t num_chunks, u; - unsigned char tmp[2]; - int prf_id; - - if (cc->application_data != 1) { - return 0; - } - chunks[0].data = cc->client_random; - chunks[0].len = sizeof cc->client_random; - chunks[1].data = cc->server_random; - chunks[1].len = sizeof cc->server_random; - if (context != NULL) { - br_enc16be(tmp, (unsigned)context_len); - chunks[2].data = tmp; - chunks[2].len = 2; - chunks[3].data = context; - chunks[3].len = context_len; - num_chunks = 4; - } else { - num_chunks = 2; - } - prf_id = BR_SSLPRF_SHA256; - for (u = 0; u < (sizeof suites_sha384) / sizeof(uint16_t); u ++) { - if (suites_sha384[u] == cc->session.cipher_suite) { - prf_id = BR_SSLPRF_SHA384; - } - } - iprf = br_ssl_engine_get_PRF(cc, prf_id); - iprf(dst, len, - cc->session.master_secret, sizeof cc->session.master_secret, - label, num_chunks, chunks); - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_lru.c b/src/tls/bearssl/ssl_lru.c deleted file mode 100644 index 42fabe2c5..000000000 --- a/src/tls/bearssl/ssl_lru.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * Each entry consists in a fixed number of bytes. Entries are concatenated - * in the store block. "Addresses" are really offsets in the block, - * expressed over 32 bits (so the cache may have size at most 4 GB, which - * "ought to be enough for everyone"). The "null address" is 0xFFFFFFFF. - * Note that since the storage block alignment is in no way guaranteed, we - * perform only accesses that can handle unaligned data. - * - * Two concurrent data structures are maintained: - * - * -- Entries are organised in a doubly-linked list; saved entries are added - * at the head, and loaded entries are moved to the head. Eviction uses - * the list tail (this is the LRU algorithm). - * - * -- Entries are indexed with a binary tree: all left descendants of a - * node have a lower session ID (in lexicographic order), while all - * right descendants have a higher session ID. The tree is heuristically - * balanced. - * - * Entry format: - * - * session ID 32 bytes - * master secret 48 bytes - * protocol version 2 bytes (big endian) - * cipher suite 2 bytes (big endian) - * list prev 4 bytes (big endian) - * list next 4 bytes (big endian) - * tree left child 4 bytes (big endian) - * tree right child 4 bytes (big endian) - * - * If an entry has a protocol version set to 0, then it is "disabled": - * it was a session pushed to the cache at some point, but it has - * been explicitly removed. - * - * We need to keep the tree balanced because an attacker could make - * handshakes, selecting some specific sessions (by reusing them) to - * try to make us make an imbalanced tree that makes lookups expensive - * (a denial-of-service attack that would persist as long as the cache - * remains, i.e. even after the attacker made all his connections). - * To do that, we replace the session ID (or the start of the session ID) - * with a HMAC value computed over the replaced part; the hash function - * implementation and the key are obtained from the server context upon - * first save() call. - * - * Theoretically, an attacker could use the exact timing of the lookup - * to infer the current tree topology, and try to revive entries to make - * it as unbalanced as possible. However, since the session ID are - * chosen randomly by the server, and the attacker cannot see the - * indexing values and must thus rely on blind selection, it should be - * exponentially difficult for the attacker to maintain a large - * imbalance. - */ -#define SESSION_ID_LEN 32 -#define MASTER_SECRET_LEN 48 - -#define SESSION_ID_OFF 0 -#define MASTER_SECRET_OFF 32 -#define VERSION_OFF 80 -#define CIPHER_SUITE_OFF 82 -#define LIST_PREV_OFF 84 -#define LIST_NEXT_OFF 88 -#define TREE_LEFT_OFF 92 -#define TREE_RIGHT_OFF 96 - -#define LRU_ENTRY_LEN 100 - -#define ADDR_NULL ((uint32_t)-1) - -#define GETSET(name, off) \ -static inline uint32_t get_ ## name(br_ssl_session_cache_lru *cc, uint32_t x) \ -{ \ - return br_dec32be(cc->store + x + (off)); \ -} \ -static inline void set_ ## name(br_ssl_session_cache_lru *cc, \ - uint32_t x, uint32_t val) \ -{ \ - br_enc32be(cc->store + x + (off), val); \ -} - -GETSET(prev, LIST_PREV_OFF) -GETSET(next, LIST_NEXT_OFF) -GETSET(left, TREE_LEFT_OFF) -GETSET(right, TREE_RIGHT_OFF) - -/* - * Transform the session ID by replacing the first N bytes with a HMAC - * value computed over these bytes, using the random key K (the HMAC - * value is truncated if needed). HMAC will use the same hash function - * as the DRBG in the SSL server context, so with SHA-256, SHA-384, - * or SHA-1, depending on what is available. - * - * The risk of collision is considered too small to be a concern; and - * the impact of a collision is low (the handshake won't succeed). This - * risk is much lower than any transmission error, which would lead to - * the same consequences. - * - * Source and destination arrays msut be disjoint. - */ -static void -mask_id(br_ssl_session_cache_lru *cc, - const unsigned char *src, unsigned char *dst) -{ - br_hmac_key_context hkc; - br_hmac_context hc; - - memcpy(dst, src, SESSION_ID_LEN); - br_hmac_key_init(&hkc, cc->hash, cc->index_key, sizeof cc->index_key); - br_hmac_init(&hc, &hkc, SESSION_ID_LEN); - br_hmac_update(&hc, src, SESSION_ID_LEN); - br_hmac_out(&hc, dst); -} - -/* - * Find a node by ID. Returned value is the node address, or ADDR_NULL if - * the node is not found. - * - * If addr_link is not NULL, then '*addr_link' is set to the address of the - * last followed link. If the found node is the root, or if the tree is - * empty, then '*addr_link' is set to ADDR_NULL. - */ -static uint32_t -find_node(br_ssl_session_cache_lru *cc, const unsigned char *id, - uint32_t *addr_link) -{ - uint32_t x, y; - - x = cc->root; - y = ADDR_NULL; - while (x != ADDR_NULL) { - int r; - - r = memcmp(id, cc->store + x + SESSION_ID_OFF, SESSION_ID_LEN); - if (r < 0) { - y = x + TREE_LEFT_OFF; - x = get_left(cc, x); - } else if (r == 0) { - if (addr_link != NULL) { - *addr_link = y; - } - return x; - } else { - y = x + TREE_RIGHT_OFF; - x = get_right(cc, x); - } - } - if (addr_link != NULL) { - *addr_link = y; - } - return ADDR_NULL; -} - -/* - * For node x, find its replacement upon removal. - * - * -- If node x has no child, then this returns ADDR_NULL. - * -- Otherwise, if node x has a left child, then the replacement is the - * rightmost left-descendent. - * -- Otherwise, the replacement is the leftmost right-descendent. - * - * If a node is returned, then '*al' is set to the address of the field - * that points to that node. Otherwise (node x has no child), '*al' is - * set to ADDR_NULL. - * - * Note that the replacement node, when found, is always a descendent - * of node 'x', so it cannot be the tree root. Thus, '*al' can be set - * to ADDR_NULL only when no node is found and ADDR_NULL is returned. - */ -static uint32_t -find_replacement_node(br_ssl_session_cache_lru *cc, uint32_t x, uint32_t *al) -{ - uint32_t y1, y2; - - y1 = get_left(cc, x); - if (y1 != ADDR_NULL) { - y2 = x + TREE_LEFT_OFF; - for (;;) { - uint32_t z; - - z = get_right(cc, y1); - if (z == ADDR_NULL) { - *al = y2; - return y1; - } - y2 = y1 + TREE_RIGHT_OFF; - y1 = z; - } - } - y1 = get_right(cc, x); - if (y1 != ADDR_NULL) { - y2 = x + TREE_RIGHT_OFF; - for (;;) { - uint32_t z; - - z = get_left(cc, y1); - if (z == ADDR_NULL) { - *al = y2; - return y1; - } - y2 = y1 + TREE_LEFT_OFF; - y1 = z; - } - } - *al = ADDR_NULL; - return ADDR_NULL; -} - -/* - * Set the link at address 'alx' to point to node 'x'. If 'alx' is - * ADDR_NULL, then this sets the tree root to 'x'. - */ -static inline void -set_link(br_ssl_session_cache_lru *cc, uint32_t alx, uint32_t x) -{ - if (alx == ADDR_NULL) { - cc->root = x; - } else { - br_enc32be(cc->store + alx, x); - } -} - -/* - * Remove node 'x' from the tree. This function shall not be called if - * node 'x' is not part of the tree. - */ -static void -remove_node(br_ssl_session_cache_lru *cc, uint32_t x) -{ - uint32_t alx, y, aly; - - /* - * Removal algorithm: - * ------------------ - * - * - If we remove the root, then the tree becomes empty. - * - * - If the removed node has no child, then we can simply remove - * it, with nothing else to do. - * - * - Otherwise, the removed node must be replaced by either its - * rightmost left-descendent, or its leftmost right-descendent. - * The replacement node itself must be removed from its current - * place. By definition, that replacement node has either no - * child, or at most a single child that will replace it in the - * tree. - */ - - /* - * Find node back and its ancestor link. If the node was the - * root, then alx is set to ADDR_NULL. - */ - find_node(cc, cc->store + x + SESSION_ID_OFF, &alx); - - /* - * Find replacement node 'y', and 'aly' is set to the address of - * the link to that replacement node. If the removed node has no - * child, then both 'y' and 'aly' are set to ADDR_NULL. - */ - y = find_replacement_node(cc, x, &aly); - - if (y != ADDR_NULL) { - uint32_t z; - - /* - * The unlinked replacement node may have one child (but - * not two) that takes its place. - */ - z = get_left(cc, y); - if (z == ADDR_NULL) { - z = get_right(cc, y); - } - set_link(cc, aly, z); - - /* - * Link the replacement node in its new place, overwriting - * the current link to the node 'x' (which removes 'x'). - */ - set_link(cc, alx, y); - - /* - * The replacement node adopts the left and right children - * of the removed node. Note that this also works even if - * the replacement node was a direct descendent of the - * removed node, since we unlinked it previously. - */ - set_left(cc, y, get_left(cc, x)); - set_right(cc, y, get_right(cc, x)); - } else { - /* - * No replacement, we simply unlink the node 'x'. - */ - set_link(cc, alx, ADDR_NULL); - } -} - -static void -lru_save(const br_ssl_session_cache_class **ctx, - br_ssl_server_context *server_ctx, - const br_ssl_session_parameters *params) -{ - br_ssl_session_cache_lru *cc; - unsigned char id[SESSION_ID_LEN]; - uint32_t x, alx; - - cc = (br_ssl_session_cache_lru *)ctx; - - /* - * If the buffer is too small, we don't record anything. This - * test avoids problems in subsequent code. - */ - if (cc->store_len < LRU_ENTRY_LEN) { - return; - } - - /* - * Upon the first save in a session cache instance, we obtain - * a random key for our indexing. - */ - if (!cc->init_done) { - br_hmac_drbg_generate(&server_ctx->eng.rng, - cc->index_key, sizeof cc->index_key); - cc->hash = br_hmac_drbg_get_hash(&server_ctx->eng.rng); - cc->init_done = 1; - } - mask_id(cc, params->session_id, id); - - /* - * Look for the node in the tree. If the same ID is already used, - * then reject it. This is a collision event, which should be - * exceedingly rare. - * Note: we do NOT record the emplacement here, because the - * removal of an entry may change the tree topology. - */ - if (find_node(cc, id, NULL) != ADDR_NULL) { - return; - } - - /* - * Find some room for the new parameters. If the cache is not - * full yet, add it to the end of the area and bump the pointer up. - * Otherwise, evict the list tail entry. Note that we already - * filtered out the case of a ridiculously small buffer that - * cannot hold any entry at all; thus, if there is no room for an - * extra entry, then the cache cannot be empty. - */ - if (cc->store_ptr > (cc->store_len - LRU_ENTRY_LEN)) { - /* - * Evict tail. If the buffer has room for a single entry, - * then this may also be the head. - */ - x = cc->tail; - cc->tail = get_prev(cc, x); - if (cc->tail == ADDR_NULL) { - cc->head = ADDR_NULL; - } else { - set_next(cc, cc->tail, ADDR_NULL); - } - - /* - * Remove the node from the tree. - */ - remove_node(cc, x); - } else { - /* - * Allocate room for new node. - */ - x = cc->store_ptr; - cc->store_ptr += LRU_ENTRY_LEN; - } - - /* - * Find the emplacement for the new node, and link it. - */ - find_node(cc, id, &alx); - set_link(cc, alx, x); - set_left(cc, x, ADDR_NULL); - set_right(cc, x, ADDR_NULL); - - /* - * New entry becomes new list head. It may also become the list - * tail if the cache was empty at that point. - */ - if (cc->head == ADDR_NULL) { - cc->tail = x; - } else { - set_prev(cc, cc->head, x); - } - set_prev(cc, x, ADDR_NULL); - set_next(cc, x, cc->head); - cc->head = x; - - /* - * Fill data in the entry. - */ - memcpy(cc->store + x + SESSION_ID_OFF, id, SESSION_ID_LEN); - memcpy(cc->store + x + MASTER_SECRET_OFF, - params->master_secret, MASTER_SECRET_LEN); - br_enc16be(cc->store + x + VERSION_OFF, params->version); - br_enc16be(cc->store + x + CIPHER_SUITE_OFF, params->cipher_suite); -} - -static int -lru_load(const br_ssl_session_cache_class **ctx, - br_ssl_server_context *server_ctx, - br_ssl_session_parameters *params) -{ - br_ssl_session_cache_lru *cc; - unsigned char id[SESSION_ID_LEN]; - uint32_t x; - - (void)server_ctx; - cc = (br_ssl_session_cache_lru *)ctx; - if (!cc->init_done) { - return 0; - } - mask_id(cc, params->session_id, id); - x = find_node(cc, id, NULL); - if (x != ADDR_NULL) { - unsigned version; - - version = br_dec16be(cc->store + x + VERSION_OFF); - if (version == 0) { - /* - * Entry is disabled, we pretend we did not find it. - * Notably, we don't move it to the front of the - * LRU list. - */ - return 0; - } - params->version = version; - params->cipher_suite = br_dec16be( - cc->store + x + CIPHER_SUITE_OFF); - memcpy(params->master_secret, - cc->store + x + MASTER_SECRET_OFF, - MASTER_SECRET_LEN); - if (x != cc->head) { - /* - * Found node is not at list head, so move - * it to the head. - */ - uint32_t p, n; - - p = get_prev(cc, x); - n = get_next(cc, x); - set_next(cc, p, n); - if (n == ADDR_NULL) { - cc->tail = p; - } else { - set_prev(cc, n, p); - } - set_prev(cc, cc->head, x); - set_next(cc, x, cc->head); - set_prev(cc, x, ADDR_NULL); - cc->head = x; - } - return 1; - } - return 0; -} - -static const br_ssl_session_cache_class lru_class = { - sizeof(br_ssl_session_cache_lru), - &lru_save, - &lru_load -}; - -/* see inner.h */ -void -br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc, - unsigned char *store, size_t store_len) -{ - cc->vtable = &lru_class; - cc->store = store; - cc->store_len = store_len; - cc->store_ptr = 0; - cc->init_done = 0; - cc->head = ADDR_NULL; - cc->tail = ADDR_NULL; - cc->root = ADDR_NULL; -} - -/* see bearssl_ssl.h */ -void br_ssl_session_cache_lru_forget( - br_ssl_session_cache_lru *cc, const unsigned char *id) -{ - unsigned char mid[SESSION_ID_LEN]; - uint32_t addr; - - /* - * If the cache is not initialised yet, then it is empty, and - * there is nothing to forget. - */ - if (!cc->init_done) { - return; - } - - /* - * Look for the node in the tree. If found, the entry is marked - * as "disabled"; it will be reused in due course, as it ages - * through the list. - * - * We do not go through the complex moves of actually releasing - * the entry right away because explicitly forgetting sessions - * should be a rare event, meant mostly for testing purposes, - * so this is not worth the extra code size. - */ - mask_id(cc, id, mid); - addr = find_node(cc, mid, NULL); - if (addr != ADDR_NULL) { - br_enc16be(cc->store + addr + VERSION_OFF, 0); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_rec_cbc.c b/src/tls/bearssl/ssl_rec_cbc.c deleted file mode 100644 index 47980242b..000000000 --- a/src/tls/bearssl/ssl_rec_cbc.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static void -in_cbc_init(br_sslrec_in_cbc_context *cc, - const br_block_cbcdec_class *bc_impl, - const void *bc_key, size_t bc_key_len, - const br_hash_class *dig_impl, - const void *mac_key, size_t mac_key_len, size_t mac_out_len, - const void *iv) -{ - cc->vtable = &br_sslrec_in_cbc_vtable; - cc->seq = 0; - bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len); - br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); - cc->mac_len = mac_out_len; - if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); - cc->explicit_IV = 1; - } else { - memcpy(cc->iv, iv, bc_impl->block_size); - cc->explicit_IV = 0; - } -} - -static int -cbc_check_length(const br_sslrec_in_cbc_context *cc, size_t rlen) -{ - /* - * Plaintext size: at most 16384 bytes - * Padding: at most 256 bytes - * MAC: mac_len extra bytes - * TLS 1.1+: each record has an explicit IV - * - * Minimum length includes at least one byte of padding, and the - * MAC. - * - * Total length must be a multiple of the block size. - */ - size_t blen; - size_t min_len, max_len; - - blen = cc->bc.vtable->block_size; - min_len = (blen + cc->mac_len) & ~(blen - 1); - max_len = (16384 + 256 + cc->mac_len) & ~(blen - 1); - if (cc->explicit_IV) { - min_len += blen; - max_len += blen; - } - return min_len <= rlen && rlen <= max_len; -} - -/* - * Rotate array buf[] of length 'len' to the left (towards low indices) - * by 'num' bytes if ctl is 1; otherwise, leave it unchanged. This is - * constant-time. 'num' MUST be lower than 'len'. 'len' MUST be lower - * than or equal to 64. - */ -static void -cond_rotate(uint32_t ctl, unsigned char *buf, size_t len, size_t num) -{ - unsigned char tmp[64]; - size_t u, v; - - for (u = 0, v = num; u < len; u ++) { - tmp[u] = MUX(ctl, buf[v], buf[u]); - if (++ v == len) { - v = 0; - } - } - memcpy(buf, tmp, len); -} - -static unsigned char * -cbc_decrypt(br_sslrec_in_cbc_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - /* - * We represent all lengths on 32-bit integers, because: - * -- SSL record lengths always fit in 32 bits; - * -- our constant-time primitives operate on 32-bit integers. - */ - unsigned char *buf; - uint32_t u, v, len, blen, min_len, max_len; - uint32_t good, pad_len, rot_count, len_withmac, len_nomac; - unsigned char tmp1[64], tmp2[64]; - int i; - br_hmac_context hc; - - buf = data; - len = *data_len; - blen = cc->bc.vtable->block_size; - - /* - * Decrypt data, and skip the explicit IV (if applicable). Note - * that the total length is supposed to have been verified by - * the caller. If there is an explicit IV, then we actually - * "decrypt" it using the implicit IV (from previous record), - * which is useless but harmless. - */ - cc->bc.vtable->run(&cc->bc.vtable, cc->iv, data, len); - if (cc->explicit_IV) { - buf += blen; - len -= blen; - } - - /* - * Compute minimum and maximum length of plaintext + MAC. These - * lengths can be inferred from the outside: they are not secret. - */ - min_len = (cc->mac_len + 256 < len) ? len - 256 : cc->mac_len; - max_len = len - 1; - - /* - * Use the last decrypted byte to compute the actual payload - * length. Take care not to underflow (we use unsigned types). - */ - pad_len = buf[max_len]; - good = LE(pad_len, (uint32_t)(max_len - min_len)); - len = MUX(good, (uint32_t)(max_len - pad_len), min_len); - - /* - * Check padding contents: all padding bytes must be equal to - * the value of pad_len. - */ - for (u = min_len; u < max_len; u ++) { - good &= LT(u, len) | EQ(buf[u], pad_len); - } - - /* - * Extract the MAC value. This is done in one pass, but results - * in a "rotated" MAC value depending on where it actually - * occurs. The 'rot_count' value is set to the offset of the - * first MAC byte within tmp1[]. - * - * min_len and max_len are also adjusted to the minimum and - * maximum lengths of the plaintext alone (without the MAC). - */ - len_withmac = (uint32_t)len; - len_nomac = len_withmac - cc->mac_len; - min_len -= cc->mac_len; - rot_count = 0; - memset(tmp1, 0, cc->mac_len); - v = 0; - for (u = min_len; u < max_len; u ++) { - tmp1[v] |= MUX(GE(u, len_nomac) & LT(u, len_withmac), - buf[u], 0x00); - rot_count = MUX(EQ(u, len_nomac), v, rot_count); - if (++ v == cc->mac_len) { - v = 0; - } - } - max_len -= cc->mac_len; - - /* - * Rotate back the MAC value. The loop below does the constant-time - * rotation in time n*log n for a MAC output of length n. We assume - * that the MAC output length is no more than 64 bytes, so the - * rotation count fits on 6 bits. - */ - for (i = 5; i >= 0; i --) { - uint32_t rc; - - rc = (uint32_t)1 << i; - cond_rotate(rot_count >> i, tmp1, cc->mac_len, rc); - rot_count &= ~rc; - } - - /* - * Recompute the HMAC value. The input is the concatenation of - * the sequence number (8 bytes), the record header (5 bytes), - * and the payload. - * - * At that point, min_len is the minimum plaintext length, but - * max_len still includes the MAC length. - */ - br_enc64be(tmp2, cc->seq ++); - tmp2[8] = (unsigned char)record_type; - br_enc16be(tmp2 + 9, version); - br_enc16be(tmp2 + 11, len_nomac); - br_hmac_init(&hc, &cc->mac, cc->mac_len); - br_hmac_update(&hc, tmp2, 13); - br_hmac_outCT(&hc, buf, len_nomac, min_len, max_len, tmp2); - - /* - * Compare the extracted and recomputed MAC values. - */ - for (u = 0; u < cc->mac_len; u ++) { - good &= EQ0(tmp1[u] ^ tmp2[u]); - } - - /* - * Check that the plaintext length is valid. The previous - * check was on the encrypted length, but the padding may have - * turned shorter than expected. - * - * Once this final test is done, the critical "constant-time" - * section ends and we can make conditional jumps again. - */ - good &= LE(len_nomac, 16384); - - if (!good) { - return 0; - } - *data_len = len_nomac; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable = { - { - sizeof(br_sslrec_in_cbc_context), - (int (*)(const br_sslrec_in_class *const *, size_t)) - &cbc_check_length, - (unsigned char *(*)(const br_sslrec_in_class **, - int, unsigned, void *, size_t *)) - &cbc_decrypt - }, - (void (*)(const br_sslrec_in_cbc_class **, - const br_block_cbcdec_class *, const void *, size_t, - const br_hash_class *, const void *, size_t, size_t, - const void *)) - &in_cbc_init -}; - -/* - * For CBC output: - * - * -- With TLS 1.1+, there is an explicit IV. Generation method uses - * HMAC, computed over the current sequence number, and the current MAC - * key. The resulting value is truncated to the size of a block, and - * added at the head of the plaintext; it will get encrypted along with - * the data. This custom generation mechanism is "safe" under the - * assumption that HMAC behaves like a random oracle; since the MAC for - * a record is computed over the concatenation of the sequence number, - * the record header and the plaintext, the HMAC-for-IV will not collide - * with the normal HMAC. - * - * -- With TLS 1.0, for application data, we want to enforce a 1/n-1 - * split, as a countermeasure against chosen-plaintext attacks. We thus - * need to leave some room in the buffer for that extra record. - */ - -static void -out_cbc_init(br_sslrec_out_cbc_context *cc, - const br_block_cbcenc_class *bc_impl, - const void *bc_key, size_t bc_key_len, - const br_hash_class *dig_impl, - const void *mac_key, size_t mac_key_len, size_t mac_out_len, - const void *iv) -{ - cc->vtable = &br_sslrec_out_cbc_vtable; - cc->seq = 0; - bc_impl->init(&cc->bc.vtable, bc_key, bc_key_len); - br_hmac_key_init(&cc->mac, dig_impl, mac_key, mac_key_len); - cc->mac_len = mac_out_len; - if (iv == NULL) { - memset(cc->iv, 0, sizeof cc->iv); - cc->explicit_IV = 1; - } else { - memcpy(cc->iv, iv, bc_impl->block_size); - cc->explicit_IV = 0; - } -} - -static void -cbc_max_plaintext(const br_sslrec_out_cbc_context *cc, - size_t *start, size_t *end) -{ - size_t blen, len; - - blen = cc->bc.vtable->block_size; - if (cc->explicit_IV) { - *start += blen; - } else { - *start += 4 + ((cc->mac_len + blen + 1) & ~(blen - 1)); - } - len = (*end - *start) & ~(blen - 1); - len -= 1 + cc->mac_len; - if (len > 16384) { - len = 16384; - } - *end = *start + len; -} - -static unsigned char * -cbc_encrypt(br_sslrec_out_cbc_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf, *rbuf; - size_t len, blen, plen; - unsigned char tmp[13]; - br_hmac_context hc; - - buf = data; - len = *data_len; - blen = cc->bc.vtable->block_size; - - /* - * If using TLS 1.0, with more than one byte of plaintext, and - * the record is application data, then we need to compute - * a "split". We do not perform the split on other record types - * because it turned out that some existing, deployed - * implementations of SSL/TLS do not tolerate the splitting of - * some message types (in particular the Finished message). - * - * If using TLS 1.1+, then there is an explicit IV. We produce - * that IV by adding an extra initial plaintext block, whose - * value is computed with HMAC over the record sequence number. - */ - if (cc->explicit_IV) { - /* - * We use here the fact that all the HMAC variants we - * support can produce at least 16 bytes, while all the - * block ciphers we support have blocks of no more than - * 16 bytes. Thus, we can always truncate the HMAC output - * down to the block size. - */ - br_enc64be(tmp, cc->seq); - br_hmac_init(&hc, &cc->mac, blen); - br_hmac_update(&hc, tmp, 8); - br_hmac_out(&hc, buf - blen); - rbuf = buf - blen - 5; - } else { - if (len > 1 && record_type == BR_SSL_APPLICATION_DATA) { - /* - * To do the split, we use a recursive invocation; - * since we only give one byte to the inner call, - * the recursion stops there. - * - * We need to compute the exact size of the extra - * record, so that the two resulting records end up - * being sequential in RAM. - * - * We use here the fact that cbc_max_plaintext() - * adjusted the start offset to leave room for the - * initial fragment. - */ - size_t xlen; - - rbuf = buf - 4 - - ((cc->mac_len + blen + 1) & ~(blen - 1)); - rbuf[0] = buf[0]; - xlen = 1; - rbuf = cbc_encrypt(cc, record_type, - version, rbuf, &xlen); - buf ++; - len --; - } else { - rbuf = buf - 5; - } - } - - /* - * Compute MAC. - */ - br_enc64be(tmp, cc->seq ++); - tmp[8] = record_type; - br_enc16be(tmp + 9, version); - br_enc16be(tmp + 11, len); - br_hmac_init(&hc, &cc->mac, cc->mac_len); - br_hmac_update(&hc, tmp, 13); - br_hmac_update(&hc, buf, len); - br_hmac_out(&hc, buf + len); - len += cc->mac_len; - - /* - * Add padding. - */ - plen = blen - (len & (blen - 1)); - memset(buf + len, (unsigned)plen - 1, plen); - len += plen; - - /* - * If an explicit IV is used, the corresponding extra block was - * already put in place earlier; we just have to account for it - * here. - */ - if (cc->explicit_IV) { - buf -= blen; - len += blen; - } - - /* - * Encrypt the whole thing. If there is an explicit IV, we also - * encrypt it, which is fine (encryption of a uniformly random - * block is still a uniformly random block). - */ - cc->bc.vtable->run(&cc->bc.vtable, cc->iv, buf, len); - - /* - * Add the header and return. - */ - buf[-5] = record_type; - br_enc16be(buf - 4, version); - br_enc16be(buf - 2, len); - *data_len = (size_t)((buf + len) - rbuf); - return rbuf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable = { - { - sizeof(br_sslrec_out_cbc_context), - (void (*)(const br_sslrec_out_class *const *, - size_t *, size_t *)) - &cbc_max_plaintext, - (unsigned char *(*)(const br_sslrec_out_class **, - int, unsigned, void *, size_t *)) - &cbc_encrypt - }, - (void (*)(const br_sslrec_out_cbc_class **, - const br_block_cbcenc_class *, const void *, size_t, - const br_hash_class *, const void *, size_t, size_t, - const void *)) - &out_cbc_init -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_rec_ccm.c b/src/tls/bearssl/ssl_rec_ccm.c deleted file mode 100644 index f46c30ac0..000000000 --- a/src/tls/bearssl/ssl_rec_ccm.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2018 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * CCM initialisation. This does everything except setting the vtable, - * which depends on whether this is a context for encrypting or for - * decrypting. - */ -static void -gen_ccm_init(br_sslrec_ccm_context *cc, - const br_block_ctrcbc_class *bc_impl, - const void *key, size_t key_len, - const void *iv, size_t tag_len) -{ - cc->seq = 0; - bc_impl->init(&cc->bc.vtable, key, key_len); - memcpy(cc->iv, iv, sizeof cc->iv); - cc->tag_len = tag_len; -} - -static void -in_ccm_init(br_sslrec_ccm_context *cc, - const br_block_ctrcbc_class *bc_impl, - const void *key, size_t key_len, - const void *iv, size_t tag_len) -{ - cc->vtable.in = &br_sslrec_in_ccm_vtable; - gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len); -} - -static int -ccm_check_length(const br_sslrec_ccm_context *cc, size_t rlen) -{ - /* - * CCM overhead is 8 bytes for nonce_explicit, and the tag - * (normally 8 or 16 bytes, depending on cipher suite). - */ - size_t over; - - over = 8 + cc->tag_len; - return rlen >= over && rlen <= (16384 + over); -} - -static unsigned char * -ccm_decrypt(br_sslrec_ccm_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - br_ccm_context zc; - unsigned char *buf; - unsigned char nonce[12], header[13]; - size_t len; - - buf = (unsigned char *)data + 8; - len = *data_len - (8 + cc->tag_len); - - /* - * Make nonce (implicit + explicit parts). - */ - memcpy(nonce, cc->iv, sizeof cc->iv); - memcpy(nonce + 4, data, 8); - - /* - * Assemble synthetic header for the AAD. - */ - br_enc64be(header, cc->seq ++); - header[8] = (unsigned char)record_type; - br_enc16be(header + 9, version); - br_enc16be(header + 11, len); - - /* - * Perform CCM decryption. - */ - br_ccm_init(&zc, &cc->bc.vtable); - br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len); - br_ccm_aad_inject(&zc, header, sizeof header); - br_ccm_flip(&zc); - br_ccm_run(&zc, 0, buf, len); - if (!br_ccm_check_tag(&zc, buf + len)) { - return NULL; - } - *data_len = len; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable = { - { - sizeof(br_sslrec_ccm_context), - (int (*)(const br_sslrec_in_class *const *, size_t)) - &ccm_check_length, - (unsigned char *(*)(const br_sslrec_in_class **, - int, unsigned, void *, size_t *)) - &ccm_decrypt - }, - (void (*)(const br_sslrec_in_ccm_class **, - const br_block_ctrcbc_class *, const void *, size_t, - const void *, size_t)) - &in_ccm_init -}; - -static void -out_ccm_init(br_sslrec_ccm_context *cc, - const br_block_ctrcbc_class *bc_impl, - const void *key, size_t key_len, - const void *iv, size_t tag_len) -{ - cc->vtable.out = &br_sslrec_out_ccm_vtable; - gen_ccm_init(cc, bc_impl, key, key_len, iv, tag_len); -} - -static void -ccm_max_plaintext(const br_sslrec_ccm_context *cc, - size_t *start, size_t *end) -{ - size_t len; - - *start += 8; - len = *end - *start - cc->tag_len; - if (len > 16384) { - len = 16384; - } - *end = *start + len; -} - -static unsigned char * -ccm_encrypt(br_sslrec_ccm_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - br_ccm_context zc; - unsigned char *buf; - unsigned char nonce[12], header[13]; - size_t len; - - buf = (unsigned char *)data; - len = *data_len; - - /* - * Make nonce; the explicit part is an encoding of the sequence - * number. - */ - memcpy(nonce, cc->iv, sizeof cc->iv); - br_enc64be(nonce + 4, cc->seq); - - /* - * Assemble synthetic header for the AAD. - */ - br_enc64be(header, cc->seq ++); - header[8] = (unsigned char)record_type; - br_enc16be(header + 9, version); - br_enc16be(header + 11, len); - - /* - * Perform CCM encryption. - */ - br_ccm_init(&zc, &cc->bc.vtable); - br_ccm_reset(&zc, nonce, sizeof nonce, sizeof header, len, cc->tag_len); - br_ccm_aad_inject(&zc, header, sizeof header); - br_ccm_flip(&zc); - br_ccm_run(&zc, 1, buf, len); - br_ccm_get_tag(&zc, buf + len); - - /* - * Assemble header and adjust pointer/length. - */ - len += 8 + cc->tag_len; - buf -= 13; - memcpy(buf + 5, nonce + 4, 8); - buf[0] = (unsigned char)record_type; - br_enc16be(buf + 1, version); - br_enc16be(buf + 3, len); - *data_len = len + 5; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable = { - { - sizeof(br_sslrec_ccm_context), - (void (*)(const br_sslrec_out_class *const *, - size_t *, size_t *)) - &ccm_max_plaintext, - (unsigned char *(*)(const br_sslrec_out_class **, - int, unsigned, void *, size_t *)) - &ccm_encrypt - }, - (void (*)(const br_sslrec_out_ccm_class **, - const br_block_ctrcbc_class *, const void *, size_t, - const void *, size_t)) - &out_ccm_init -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_rec_chapol.c b/src/tls/bearssl/ssl_rec_chapol.c deleted file mode 100644 index bb612f6e7..000000000 --- a/src/tls/bearssl/ssl_rec_chapol.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static void -gen_chapol_init(br_sslrec_chapol_context *cc, - br_chacha20_run ichacha, br_poly1305_run ipoly, - const void *key, const void *iv) -{ - cc->seq = 0; - cc->ichacha = ichacha; - cc->ipoly = ipoly; - memcpy(cc->key, key, sizeof cc->key); - memcpy(cc->iv, iv, sizeof cc->iv); -} - -static void -gen_chapol_process(br_sslrec_chapol_context *cc, - int record_type, unsigned version, void *data, size_t len, - void *tag, int encrypt) -{ - unsigned char header[13]; - unsigned char nonce[12]; - uint64_t seq; - size_t u; - - seq = cc->seq ++; - br_enc64be(header, seq); - header[8] = (unsigned char)record_type; - br_enc16be(header + 9, version); - br_enc16be(header + 11, len); - memcpy(nonce, cc->iv, 12); - for (u = 0; u < 8; u ++) { - nonce[11 - u] ^= (unsigned char)seq; - seq >>= 8; - } - cc->ipoly(cc->key, nonce, data, len, header, sizeof header, - tag, cc->ichacha, encrypt); -} - -static void -in_chapol_init(br_sslrec_chapol_context *cc, - br_chacha20_run ichacha, br_poly1305_run ipoly, - const void *key, const void *iv) -{ - cc->vtable.in = &br_sslrec_in_chapol_vtable; - gen_chapol_init(cc, ichacha, ipoly, key, iv); -} - -static int -chapol_check_length(const br_sslrec_chapol_context *cc, size_t rlen) -{ - /* - * Overhead is just the authentication tag (16 bytes). - */ - (void)cc; - return rlen >= 16 && rlen <= (16384 + 16); -} - -static unsigned char * -chapol_decrypt(br_sslrec_chapol_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf; - size_t u, len; - unsigned char tag[16]; - unsigned bad; - - buf = data; - len = *data_len - 16; - gen_chapol_process(cc, record_type, version, buf, len, tag, 0); - bad = 0; - for (u = 0; u < 16; u ++) { - bad |= tag[u] ^ buf[len + u]; - } - if (bad) { - return NULL; - } - *data_len = len; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable = { - { - sizeof(br_sslrec_chapol_context), - (int (*)(const br_sslrec_in_class *const *, size_t)) - &chapol_check_length, - (unsigned char *(*)(const br_sslrec_in_class **, - int, unsigned, void *, size_t *)) - &chapol_decrypt - }, - (void (*)(const br_sslrec_in_chapol_class **, - br_chacha20_run, br_poly1305_run, - const void *, const void *)) - &in_chapol_init -}; - -static void -out_chapol_init(br_sslrec_chapol_context *cc, - br_chacha20_run ichacha, br_poly1305_run ipoly, - const void *key, const void *iv) -{ - cc->vtable.out = &br_sslrec_out_chapol_vtable; - gen_chapol_init(cc, ichacha, ipoly, key, iv); -} - -static void -chapol_max_plaintext(const br_sslrec_chapol_context *cc, - size_t *start, size_t *end) -{ - size_t len; - - (void)cc; - len = *end - *start - 16; - if (len > 16384) { - len = 16384; - } - *end = *start + len; -} - -static unsigned char * -chapol_encrypt(br_sslrec_chapol_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf; - size_t len; - - buf = data; - len = *data_len; - gen_chapol_process(cc, record_type, version, buf, len, buf + len, 1); - buf -= 5; - buf[0] = (unsigned char)record_type; - br_enc16be(buf + 1, version); - br_enc16be(buf + 3, len + 16); - *data_len = len + 21; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable = { - { - sizeof(br_sslrec_chapol_context), - (void (*)(const br_sslrec_out_class *const *, - size_t *, size_t *)) - &chapol_max_plaintext, - (unsigned char *(*)(const br_sslrec_out_class **, - int, unsigned, void *, size_t *)) - &chapol_encrypt - }, - (void (*)(const br_sslrec_out_chapol_class **, - br_chacha20_run, br_poly1305_run, - const void *, const void *)) - &out_chapol_init -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_rec_gcm.c b/src/tls/bearssl/ssl_rec_gcm.c deleted file mode 100644 index 4492f1ca9..000000000 --- a/src/tls/bearssl/ssl_rec_gcm.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* - * GCM initialisation. This does everything except setting the vtable, - * which depends on whether this is a context for encrypting or for - * decrypting. - */ -static void -gen_gcm_init(br_sslrec_gcm_context *cc, - const br_block_ctr_class *bc_impl, - const void *key, size_t key_len, - br_ghash gh_impl, - const void *iv) -{ - unsigned char tmp[12]; - - cc->seq = 0; - bc_impl->init(&cc->bc.vtable, key, key_len); - cc->gh = gh_impl; - memcpy(cc->iv, iv, sizeof cc->iv); - memset(cc->h, 0, sizeof cc->h); - memset(tmp, 0, sizeof tmp); - bc_impl->run(&cc->bc.vtable, tmp, 0, cc->h, sizeof cc->h); -} - -static void -in_gcm_init(br_sslrec_gcm_context *cc, - const br_block_ctr_class *bc_impl, - const void *key, size_t key_len, - br_ghash gh_impl, - const void *iv) -{ - cc->vtable.in = &br_sslrec_in_gcm_vtable; - gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv); -} - -static int -gcm_check_length(const br_sslrec_gcm_context *cc, size_t rlen) -{ - /* - * GCM adds a fixed overhead: - * 8 bytes for the nonce_explicit (before the ciphertext) - * 16 bytes for the authentication tag (after the ciphertext) - */ - (void)cc; - return rlen >= 24 && rlen <= (16384 + 24); -} - -/* - * Compute the authentication tag. The value written in 'tag' must still - * be CTR-encrypted. - */ -static void -do_tag(br_sslrec_gcm_context *cc, - int record_type, unsigned version, - void *data, size_t len, void *tag) -{ - unsigned char header[13]; - unsigned char footer[16]; - - /* - * Compute authentication tag. Three elements must be injected in - * sequence, each possibly 0-padded to reach a length multiple - * of the block size: the 13-byte header (sequence number, record - * type, protocol version, record length), the cipher text, and - * the word containing the encodings of the bit lengths of the two - * other elements. - */ - br_enc64be(header, cc->seq ++); - header[8] = (unsigned char)record_type; - br_enc16be(header + 9, version); - br_enc16be(header + 11, len); - br_enc64be(footer, (uint64_t)(sizeof header) << 3); - br_enc64be(footer + 8, (uint64_t)len << 3); - memset(tag, 0, 16); - cc->gh(tag, cc->h, header, sizeof header); - cc->gh(tag, cc->h, data, len); - cc->gh(tag, cc->h, footer, sizeof footer); -} - -/* - * Do CTR encryption. This also does CTR encryption of a single block at - * address 'xortag' with the counter value appropriate for the final - * processing of the authentication tag. - */ -static void -do_ctr(br_sslrec_gcm_context *cc, const void *nonce, void *data, size_t len, - void *xortag) -{ - unsigned char iv[12]; - - memcpy(iv, cc->iv, 4); - memcpy(iv + 4, nonce, 8); - cc->bc.vtable->run(&cc->bc.vtable, iv, 2, data, len); - cc->bc.vtable->run(&cc->bc.vtable, iv, 1, xortag, 16); -} - -static unsigned char * -gcm_decrypt(br_sslrec_gcm_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf; - size_t len, u; - uint32_t bad; - unsigned char tag[16]; - - buf = (unsigned char *)data + 8; - len = *data_len - 24; - do_tag(cc, record_type, version, buf, len, tag); - do_ctr(cc, data, buf, len, tag); - - /* - * Compare the computed tag with the value from the record. It - * is possibly useless to do a constant-time comparison here, - * but it does not hurt. - */ - bad = 0; - for (u = 0; u < 16; u ++) { - bad |= tag[u] ^ buf[len + u]; - } - if (bad) { - return NULL; - } - *data_len = len; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable = { - { - sizeof(br_sslrec_gcm_context), - (int (*)(const br_sslrec_in_class *const *, size_t)) - &gcm_check_length, - (unsigned char *(*)(const br_sslrec_in_class **, - int, unsigned, void *, size_t *)) - &gcm_decrypt - }, - (void (*)(const br_sslrec_in_gcm_class **, - const br_block_ctr_class *, const void *, size_t, - br_ghash, const void *)) - &in_gcm_init -}; - -static void -out_gcm_init(br_sslrec_gcm_context *cc, - const br_block_ctr_class *bc_impl, - const void *key, size_t key_len, - br_ghash gh_impl, - const void *iv) -{ - cc->vtable.out = &br_sslrec_out_gcm_vtable; - gen_gcm_init(cc, bc_impl, key, key_len, gh_impl, iv); -} - -static void -gcm_max_plaintext(const br_sslrec_gcm_context *cc, - size_t *start, size_t *end) -{ - size_t len; - - (void)cc; - *start += 8; - len = *end - *start - 16; - if (len > 16384) { - len = 16384; - } - *end = *start + len; -} - -static unsigned char * -gcm_encrypt(br_sslrec_gcm_context *cc, - int record_type, unsigned version, void *data, size_t *data_len) -{ - unsigned char *buf; - size_t u, len; - unsigned char tmp[16]; - - buf = (unsigned char *)data; - len = *data_len; - memset(tmp, 0, sizeof tmp); - br_enc64be(buf - 8, cc->seq); - do_ctr(cc, buf - 8, buf, len, tmp); - do_tag(cc, record_type, version, buf, len, buf + len); - for (u = 0; u < 16; u ++) { - buf[len + u] ^= tmp[u]; - } - len += 24; - buf -= 13; - buf[0] = (unsigned char)record_type; - br_enc16be(buf + 1, version); - br_enc16be(buf + 3, len); - *data_len = len + 5; - return buf; -} - -/* see bearssl_ssl.h */ -const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable = { - { - sizeof(br_sslrec_gcm_context), - (void (*)(const br_sslrec_out_class *const *, - size_t *, size_t *)) - &gcm_max_plaintext, - (unsigned char *(*)(const br_sslrec_out_class **, - int, unsigned, void *, size_t *)) - &gcm_encrypt - }, - (void (*)(const br_sslrec_out_gcm_class **, - const br_block_ctr_class *, const void *, size_t, - br_ghash, const void *)) - &out_gcm_init -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_scert_single_ec.c b/src/tls/bearssl/ssl_scert_single_ec.c deleted file mode 100644 index 164709b1c..000000000 --- a/src/tls/bearssl/ssl_scert_single_ec.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static int -se_choose(const br_ssl_server_policy_class **pctx, - const br_ssl_server_context *cc, - br_ssl_server_choices *choices) -{ - br_ssl_server_policy_ec_context *pc; - const br_suite_translated *st; - size_t u, st_num; - unsigned hash_id; - - pc = (br_ssl_server_policy_ec_context *)pctx; - st = br_ssl_server_get_client_suites(cc, &st_num); - hash_id = br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc) >> 8); - if (cc->eng.session.version < BR_TLS12) { - hash_id = br_sha1_ID; - } - choices->chain = pc->chain; - choices->chain_len = pc->chain_len; - for (u = 0; u < st_num; u ++) { - unsigned tt; - - tt = st[u][1]; - switch (tt >> 12) { - case BR_SSLKEYX_ECDH_RSA: - if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 - && pc->cert_issuer_key_type == BR_KEYTYPE_RSA) - { - choices->cipher_suite = st[u][0]; - return 1; - } - break; - case BR_SSLKEYX_ECDH_ECDSA: - if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 - && pc->cert_issuer_key_type == BR_KEYTYPE_EC) - { - choices->cipher_suite = st[u][0]; - return 1; - } - break; - case BR_SSLKEYX_ECDHE_ECDSA: - if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 - && hash_id != 0) - { - choices->cipher_suite = st[u][0]; - choices->algo_id = hash_id + 0xFF00; - return 1; - } - break; - } - } - return 0; -} - -static uint32_t -se_do_keyx(const br_ssl_server_policy_class **pctx, - unsigned char *data, size_t *len) -{ - br_ssl_server_policy_ec_context *pc; - uint32_t r; - size_t xoff, xlen; - - pc = (br_ssl_server_policy_ec_context *)pctx; - r = pc->iec->mul(data, *len, pc->sk->x, pc->sk->xlen, pc->sk->curve); - xoff = pc->iec->xoff(pc->sk->curve, &xlen); - memmove(data, data + xoff, xlen); - *len = xlen; - return r; -} - -static size_t -se_do_sign(const br_ssl_server_policy_class **pctx, - unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) -{ - br_ssl_server_policy_ec_context *pc; - unsigned char hv[64]; - const br_hash_class *hc; - - algo_id &= 0xFF; - pc = (br_ssl_server_policy_ec_context *)pctx; - hc = br_multihash_getimpl(pc->mhash, algo_id); - if (hc == NULL) { - return 0; - } - memcpy(hv, data, hv_len); - if (len < 139) { - return 0; - } - return pc->iecdsa(pc->iec, hc, hv, pc->sk, data); -} - -static const br_ssl_server_policy_class se_policy_vtable = { - sizeof(br_ssl_server_policy_ec_context), - se_choose, - se_do_keyx, - se_do_sign -}; - -/* see bearssl_ssl.h */ -void -br_ssl_server_set_single_ec(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk, unsigned allowed_usages, - unsigned cert_issuer_key_type, - const br_ec_impl *iec, br_ecdsa_sign iecdsa) -{ - cc->chain_handler.single_ec.vtable = &se_policy_vtable; - cc->chain_handler.single_ec.chain = chain; - cc->chain_handler.single_ec.chain_len = chain_len; - cc->chain_handler.single_ec.sk = sk; - cc->chain_handler.single_ec.allowed_usages = allowed_usages; - cc->chain_handler.single_ec.cert_issuer_key_type = cert_issuer_key_type; - cc->chain_handler.single_ec.mhash = &cc->eng.mhash; - cc->chain_handler.single_ec.iec = iec; - cc->chain_handler.single_ec.iecdsa = iecdsa; - cc->policy_vtable = &cc->chain_handler.single_ec.vtable; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_scert_single_rsa.c b/src/tls/bearssl/ssl_scert_single_rsa.c deleted file mode 100644 index d8ebac1aa..000000000 --- a/src/tls/bearssl/ssl_scert_single_rsa.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -static int -sr_choose(const br_ssl_server_policy_class **pctx, - const br_ssl_server_context *cc, - br_ssl_server_choices *choices) -{ - br_ssl_server_policy_rsa_context *pc; - const br_suite_translated *st; - size_t u, st_num; - unsigned hash_id; - int fh; - - pc = (br_ssl_server_policy_rsa_context *)pctx; - st = br_ssl_server_get_client_suites(cc, &st_num); - if (cc->eng.session.version < BR_TLS12) { - hash_id = 0; - fh = 1; - } else { - hash_id = br_ssl_choose_hash( - br_ssl_server_get_client_hashes(cc)); - fh = (hash_id != 0); - } - choices->chain = pc->chain; - choices->chain_len = pc->chain_len; - for (u = 0; u < st_num; u ++) { - unsigned tt; - - tt = st[u][1]; - switch (tt >> 12) { - case BR_SSLKEYX_RSA: - if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0) { - choices->cipher_suite = st[u][0]; - return 1; - } - break; - case BR_SSLKEYX_ECDHE_RSA: - if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 && fh) { - choices->cipher_suite = st[u][0]; - choices->algo_id = hash_id + 0xFF00; - return 1; - } - break; - } - } - return 0; -} - -static uint32_t -sr_do_keyx(const br_ssl_server_policy_class **pctx, - unsigned char *data, size_t *len) -{ - br_ssl_server_policy_rsa_context *pc; - - pc = (br_ssl_server_policy_rsa_context *)pctx; - return br_rsa_ssl_decrypt(pc->irsacore, pc->sk, data, *len); -} - -/* - * OID for hash functions in RSA signatures. - */ -static const unsigned char HASH_OID_SHA1[] = { - 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A -}; - -static const unsigned char HASH_OID_SHA224[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04 -}; - -static const unsigned char HASH_OID_SHA256[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 -}; - -static const unsigned char HASH_OID_SHA384[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 -}; - -static const unsigned char HASH_OID_SHA512[] = { - 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 -}; - -static const unsigned char *HASH_OID[] = { - HASH_OID_SHA1, - HASH_OID_SHA224, - HASH_OID_SHA256, - HASH_OID_SHA384, - HASH_OID_SHA512 -}; - -static size_t -sr_do_sign(const br_ssl_server_policy_class **pctx, - unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) -{ - br_ssl_server_policy_rsa_context *pc; - unsigned char hv[64]; - size_t sig_len; - const unsigned char *hash_oid; - - pc = (br_ssl_server_policy_rsa_context *)pctx; - memcpy(hv, data, hv_len); - algo_id &= 0xFF; - if (algo_id == 0) { - hash_oid = NULL; - } else if (algo_id >= 2 && algo_id <= 6) { - hash_oid = HASH_OID[algo_id - 2]; - } else { - return 0; - } - sig_len = (pc->sk->n_bitlen + 7) >> 3; - if (len < sig_len) { - return 0; - } - return pc->irsasign(hash_oid, hv, hv_len, pc->sk, data) ? sig_len : 0; -} - -static const br_ssl_server_policy_class sr_policy_vtable = { - sizeof(br_ssl_server_policy_rsa_context), - sr_choose, - sr_do_keyx, - sr_do_sign -}; - -/* see bearssl_ssl.h */ -void -br_ssl_server_set_single_rsa(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk, unsigned allowed_usages, - br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign) -{ - cc->chain_handler.single_rsa.vtable = &sr_policy_vtable; - cc->chain_handler.single_rsa.chain = chain; - cc->chain_handler.single_rsa.chain_len = chain_len; - cc->chain_handler.single_rsa.sk = sk; - cc->chain_handler.single_rsa.allowed_usages = allowed_usages; - cc->chain_handler.single_rsa.irsacore = irsacore; - cc->chain_handler.single_rsa.irsasign = irsasign; - cc->policy_vtable = &cc->chain_handler.single_rsa.vtable; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server.c b/src/tls/bearssl/ssl_server.c deleted file mode 100644 index 22fa641e1..000000000 --- a/src/tls/bearssl/ssl_server.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_zero(br_ssl_server_context *cc) -{ - /* - * For really standard C, we should explicitly set to NULL all - * pointers, and 0 all other fields. However, on all our target - * architectures, a direct memset() will work, be faster, and - * use a lot less code. - */ - memset(cc, 0, sizeof *cc); -} - -/* see bearssl_ssl.h */ -int -br_ssl_server_reset(br_ssl_server_context *cc) -{ - br_ssl_engine_set_buffer(&cc->eng, NULL, 0, 0); - if (!br_ssl_engine_init_rand(&cc->eng)) { - return 0; - } - cc->eng.reneg = 0; - br_ssl_engine_hs_reset(&cc->eng, - br_ssl_hs_server_init_main, br_ssl_hs_server_run); - return br_ssl_engine_last_error(&cc->eng) == BR_ERR_OK; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_full_ec.c b/src/tls/bearssl/ssl_server_full_ec.c deleted file mode 100644 index 3c7792594..000000000 --- a/src/tls/bearssl/ssl_server_full_ec.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_full_ec(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - unsigned cert_issuer_key_type, const br_ec_private_key *sk) -{ - /* - * The "full" profile supports all implemented cipher suites. - * - * Rationale for suite order, from most important to least - * important rule: - * - * -- Don't use 3DES if AES is available. - * -- Try to have Forward Secrecy (ECDHE suite) if possible. - * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller). - * -- GCM is better than CCM and CBC. CCM is better than CBC. - * -- CCM is better than CCM_8. - * -- AES-128 is preferred over AES-256 (AES-128 is already - * strong enough, and AES-256 is 40% more expensive). - * - * Note that for ECDH suites, the list will be automatically - * filtered based on the issuing CA key type. - */ - static const uint16_t suites[] = { - BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - }; - - /* - * All hash functions are activated. - * Note: the X.509 validation engine will nonetheless refuse to - * validate signatures that use MD5 as hash function. - */ - static const br_hash_class *hashes[] = { - &br_md5_vtable, - &br_sha1_vtable, - &br_sha224_vtable, - &br_sha256_vtable, - &br_sha384_vtable, - &br_sha512_vtable - }; - - int id; - - /* - * Reset server context and set supported versions from TLS-1.0 - * to TLS-1.2 (inclusive). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_default_ec(&cc->eng); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_ec(cc, chain, chain_len, sk, - BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, - cert_issuer_key_type, - br_ssl_engine_get_ec(&cc->eng), -#if BR_LOMUL - br_ecdsa_i15_sign_asn1 -#else - br_ecdsa_i31_sign_asn1 -#endif - ); - - /* - * Set supported hash functions. - */ - for (id = br_md5_ID; id <= br_sha512_ID; id ++) { - const br_hash_class *hc; - - hc = hashes[id - 1]; - br_ssl_engine_set_hash(&cc->eng, id, hc); - } - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_cbc(&cc->eng); - br_ssl_engine_set_default_aes_ccm(&cc->eng); - br_ssl_engine_set_default_aes_gcm(&cc->eng); - br_ssl_engine_set_default_des_cbc(&cc->eng); - br_ssl_engine_set_default_chapol(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_full_rsa.c b/src/tls/bearssl/ssl_server_full_rsa.c deleted file mode 100644 index 3ce698a8a..000000000 --- a/src/tls/bearssl/ssl_server_full_rsa.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_full_rsa(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk) -{ - /* - * The "full" profile supports all implemented cipher suites. - * - * Rationale for suite order, from most important to least - * important rule: - * - * -- Don't use 3DES if AES is available. - * -- Try to have Forward Secrecy (ECDHE suite) if possible. - * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller). - * -- GCM is better than CBC. - * -- AES-128 is preferred over AES-256 (AES-128 is already - * strong enough, and AES-256 is 40% more expensive). - */ - static const uint16_t suites[] = { - BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_RSA_WITH_AES_128_GCM_SHA256, - BR_TLS_RSA_WITH_AES_256_GCM_SHA384, - BR_TLS_RSA_WITH_AES_128_CCM, - BR_TLS_RSA_WITH_AES_256_CCM, - BR_TLS_RSA_WITH_AES_128_CCM_8, - BR_TLS_RSA_WITH_AES_256_CCM_8, - BR_TLS_RSA_WITH_AES_128_CBC_SHA256, - BR_TLS_RSA_WITH_AES_256_CBC_SHA256, - BR_TLS_RSA_WITH_AES_128_CBC_SHA, - BR_TLS_RSA_WITH_AES_256_CBC_SHA, - BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA - }; - - /* - * All hash functions are activated. - * Note: the X.509 validation engine will nonetheless refuse to - * validate signatures that use MD5 as hash function. - */ - static const br_hash_class *hashes[] = { - &br_md5_vtable, - &br_sha1_vtable, - &br_sha224_vtable, - &br_sha256_vtable, - &br_sha384_vtable, - &br_sha512_vtable - }; - - int id; - - /* - * Reset server context and set supported versions from TLS-1.0 - * to TLS-1.2 (inclusive). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS10, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_default_ec(&cc->eng); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, - BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, - br_rsa_private_get_default(), - br_rsa_pkcs1_sign_get_default()); - - /* - * Set supported hash functions. - */ - for (id = br_md5_ID; id <= br_sha512_ID; id ++) { - const br_hash_class *hc; - - hc = hashes[id - 1]; - br_ssl_engine_set_hash(&cc->eng, id, hc); - } - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf10(&cc->eng, &br_tls10_prf); - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_cbc(&cc->eng); - br_ssl_engine_set_default_aes_ccm(&cc->eng); - br_ssl_engine_set_default_aes_gcm(&cc->eng); - br_ssl_engine_set_default_des_cbc(&cc->eng); - br_ssl_engine_set_default_chapol(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_mine2c.c b/src/tls/bearssl/ssl_server_mine2c.c deleted file mode 100644 index 19a7b2346..000000000 --- a/src/tls/bearssl/ssl_server_mine2c.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_mine2c(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, - BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_chapol(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_mine2g.c b/src/tls/bearssl/ssl_server_mine2g.c deleted file mode 100644 index 1afbb9c90..000000000 --- a/src/tls/bearssl/ssl_server_mine2g.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_mine2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, - BR_KEYTYPE_SIGN, 0, br_rsa_i31_pkcs1_sign); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_minf2c.c b/src/tls/bearssl/ssl_server_minf2c.c deleted file mode 100644 index ef4794680..000000000 --- a/src/tls/bearssl/ssl_server_minf2c.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_minf2c(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_ec(cc, chain, chain_len, sk, - BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_chapol(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_minf2g.c b/src/tls/bearssl/ssl_server_minf2g.c deleted file mode 100644 index 60096afaa..000000000 --- a/src/tls/bearssl/ssl_server_minf2g.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_minf2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites and elliptic curve implementation (for ECDHE). - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_ec(cc, chain, chain_len, sk, - BR_KEYTYPE_SIGN, 0, &br_ec_all_m15, br_ecdsa_i31_sign_asn1); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_minr2g.c b/src/tls/bearssl/ssl_server_minr2g.c deleted file mode 100644 index 529bab59e..000000000 --- a/src/tls/bearssl/ssl_server_minr2g.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_minr2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_rsa_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_RSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites. - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_rsa(cc, chain, chain_len, sk, - BR_KEYTYPE_KEYX, br_rsa_i31_private, 0); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_minu2g.c b/src/tls/bearssl/ssl_server_minu2g.c deleted file mode 100644 index fb63d69a3..000000000 --- a/src/tls/bearssl/ssl_server_minu2g.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_minu2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites. - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_ec(cc, chain, chain_len, sk, - BR_KEYTYPE_KEYX, BR_KEYTYPE_RSA, &br_ec_all_m15, 0); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/ssl_server_minv2g.c b/src/tls/bearssl/ssl_server_minv2g.c deleted file mode 100644 index 149ab75dc..000000000 --- a/src/tls/bearssl/ssl_server_minv2g.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_ssl.h */ -void -br_ssl_server_init_minv2g(br_ssl_server_context *cc, - const br_x509_certificate *chain, size_t chain_len, - const br_ec_private_key *sk) -{ - static const uint16_t suites[] = { - BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset server context and set supported versions to TLS-1.2 (only). - */ - br_ssl_server_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * Set suites. - */ - br_ssl_engine_set_suites(&cc->eng, suites, - (sizeof suites) / (sizeof suites[0])); - - /* - * Set the "server policy": handler for the certificate chain - * and private key operations. - */ - br_ssl_server_set_single_ec(cc, chain, chain_len, sk, - BR_KEYTYPE_KEYX, BR_KEYTYPE_EC, &br_ec_all_m15, 0); - - /* - * Set supported hash functions. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/sysrng.c b/src/tls/bearssl/sysrng.c deleted file mode 100644 index 8829d5a07..000000000 --- a/src/tls/bearssl/sysrng.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2017 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#define BR_ENABLE_INTRINSICS 1 -#include "inner.h" - -#if BR_USE_URANDOM -#include -#include -#include -#include -#endif - -#if BR_USE_WIN32_RAND -#include -#include -#pragma comment(lib, "advapi32") -#endif - -#if BR_RDRAND -BR_TARGETS_X86_UP -BR_TARGET("rdrnd") -static int -seeder_rdrand(const br_prng_class **ctx) -{ - unsigned char tmp[32]; - size_t u; - - for (u = 0; u < sizeof tmp; u += sizeof(uint32_t)) { - int j; - uint32_t x; - - /* - * We use the 32-bit intrinsic so that code is compatible - * with both 32-bit and 64-bit architectures. - * - * Intel recommends trying at least 10 times in case of - * failure. - */ - for (j = 0; j < 10; j ++) { - if (_rdrand32_step(&x)) { - goto next_word; - } - } - return 0; - next_word: - br_enc32le(tmp + u, x); - } - (*ctx)->update(ctx, tmp, sizeof tmp); - return 1; -} -BR_TARGETS_X86_DOWN - -static int -rdrand_supported(void) -{ - /* - * The RDRND support is bit 30 of ECX, as returned by CPUID. - */ - return br_cpuid(0, 0, 0x40000000, 0); -} - -#endif - -#if BR_USE_URANDOM -static int -seeder_urandom(const br_prng_class **ctx) -{ - int f; - - f = open("/dev/urandom", O_RDONLY); - if (f >= 0) { - unsigned char tmp[32]; - size_t u; - - for (u = 0; u < sizeof tmp;) { - ssize_t len; - - len = read(f, tmp + u, (sizeof tmp) - u); - if (len < 0) { - if (errno == EINTR) { - continue; - } - break; - } - u += (size_t)len; - } - close(f); - if (u == sizeof tmp) { - (*ctx)->update(ctx, tmp, sizeof tmp); - return 1; - } - } - return 0; -} -#endif - -#if BR_USE_WIN32_RAND -static int -seeder_win32(const br_prng_class **ctx) -{ - HCRYPTPROV hp; - - if (CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - { - BYTE buf[32]; - BOOL r; - - r = CryptGenRandom(hp, sizeof buf, buf); - CryptReleaseContext(hp, 0); - if (r) { - (*ctx)->update(ctx, buf, sizeof buf); - return 1; - } - } - return 0; -} -#endif - -/* see bearssl_rand.h */ -br_prng_seeder -br_prng_seeder_system(const char **name) -{ -#if BR_RDRAND - if (rdrand_supported()) { - if (name != NULL) { - *name = "rdrand"; - } - return &seeder_rdrand; - } -#endif -#if BR_USE_URANDOM - if (name != NULL) { - *name = "urandom"; - } - return &seeder_urandom; -#elif BR_USE_WIN32_RAND - if (name != NULL) { - *name = "win32"; - } - return &seeder_win32; -#endif - if (name != NULL) { - *name = "none"; - } - return 0; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/x509_decoder.c b/src/tls/bearssl/x509_decoder.c deleted file mode 100644 index 615e7db0e..000000000 --- a/src/tls/bearssl/x509_decoder.c +++ /dev/null @@ -1,778 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_x509_decoder_init_main(void *t0ctx); - -void br_x509_decoder_run(void *t0ctx); - - - -#include "inner.h" - - - - - -#include "inner.h" - -#define CTX ((br_x509_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_decoder_context, cpu))) -#define CONTEXT_NAME br_x509_decoder_context - -/* see bearssl_x509.h */ -void -br_x509_decoder_init(br_x509_decoder_context *ctx, - void (*append_dn)(void *ctx, const void *buf, size_t len), - void *append_dn_ctx) -{ - memset(ctx, 0, sizeof *ctx); - /* obsolete - ctx->err = 0; - ctx->hbuf = NULL; - ctx->hlen = 0; - */ - ctx->append_dn = append_dn; - ctx->append_dn_ctx = append_dn_ctx; - ctx->cpu.dp = &ctx->dp_stack[0]; - ctx->cpu.rp = &ctx->rp_stack[0]; - br_x509_decoder_init_main(&ctx->cpu); - br_x509_decoder_run(&ctx->cpu); -} - -/* see bearssl_x509.h */ -void -br_x509_decoder_push(br_x509_decoder_context *ctx, - const void *data, size_t len) -{ - ctx->hbuf = data; - ctx->hlen = len; - br_x509_decoder_run(&ctx->cpu); -} - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x0D, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, - 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, - 0x04, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, - 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, - 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, - 0x03, 0x04, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, 0x0F, 0x1F, - 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, 0x26, 0x1E, - 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, 0x0F, 0x3F, - 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, 0x26, 0x3E, - 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13 -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x01, - 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, 0x00, 0x00, 0x1A, 0x1A, 0x00, - 0x00, 0x01, T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, - T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), - 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, copy_dn)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, decoded)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, isCA)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_x509_decoder_context, pkey_data)), 0x01, - T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, notafter_days)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, notafter_seconds)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, notbefore_days)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, notbefore_seconds)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, signer_hash_id)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, signer_key_type)), 0x00, 0x00, 0x01, - 0x80, 0x45, 0x00, 0x00, 0x01, 0x80, 0x4E, 0x00, 0x00, 0x01, 0x80, 0x54, - 0x00, 0x00, 0x01, 0x81, 0x36, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0x1B, - 0x02, 0x01, 0x13, 0x26, 0x02, 0x00, 0x0F, 0x15, 0x00, 0x00, 0x05, 0x02, - 0x34, 0x1D, 0x00, 0x00, 0x06, 0x02, 0x35, 0x1D, 0x00, 0x00, 0x01, 0x10, - 0x4F, 0x00, 0x00, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x4C, 0x00, 0x00, 0x11, - 0x05, 0x02, 0x38, 0x1D, 0x4D, 0x00, 0x00, 0x06, 0x02, 0x30, 0x1D, 0x00, - 0x00, 0x1B, 0x19, 0x01, 0x08, 0x0E, 0x26, 0x29, 0x19, 0x09, 0x00, 0x00, - 0x01, 0x30, 0x0A, 0x1B, 0x01, 0x00, 0x01, 0x09, 0x4B, 0x05, 0x02, 0x2F, - 0x1D, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x01, 0x80, 0x5A, 0x00, 0x00, - 0x01, 0x80, 0x62, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x80, - 0x74, 0x00, 0x00, 0x01, 0x80, 0x7D, 0x00, 0x00, 0x01, 0x3D, 0x00, 0x00, - 0x20, 0x11, 0x06, 0x04, 0x2B, 0x6B, 0x7A, 0x71, 0x00, 0x04, 0x01, 0x00, - 0x3D, 0x25, 0x01, 0x00, 0x3C, 0x25, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x6D, - 0x6D, 0x70, 0x1B, 0x01, 0x20, 0x11, 0x06, 0x11, 0x1A, 0x4C, 0x6B, 0x70, - 0x01, 0x02, 0x50, 0x6E, 0x01, 0x02, 0x12, 0x06, 0x02, 0x39, 0x1D, 0x51, - 0x70, 0x01, 0x02, 0x50, 0x6C, 0x6D, 0x7A, 0x6D, 0x7A, 0x6D, 0x65, 0x43, - 0x24, 0x42, 0x24, 0x65, 0x41, 0x24, 0x40, 0x24, 0x51, 0x01, 0x01, 0x3C, - 0x25, 0x6D, 0x7A, 0x01, 0x00, 0x3C, 0x25, 0x6D, 0x6D, 0x60, 0x05, 0x02, - 0x39, 0x1D, 0x74, 0x1C, 0x06, 0x1C, 0x7A, 0x61, 0x6D, 0x3F, 0x68, 0x03, - 0x00, 0x3F, 0x26, 0x02, 0x00, 0x09, 0x26, 0x02, 0x00, 0x0A, 0x68, 0x03, - 0x01, 0x51, 0x51, 0x02, 0x00, 0x02, 0x01, 0x18, 0x04, 0x1E, 0x5A, 0x1C, - 0x06, 0x18, 0x64, 0x03, 0x02, 0x51, 0x61, 0x1B, 0x03, 0x03, 0x1B, 0x3F, - 0x23, 0x0D, 0x06, 0x02, 0x33, 0x1D, 0x62, 0x02, 0x02, 0x02, 0x03, 0x17, - 0x04, 0x02, 0x39, 0x1D, 0x51, 0x01, 0x00, 0x3E, 0x25, 0x71, 0x01, 0x21, - 0x5B, 0x01, 0x22, 0x5B, 0x1B, 0x01, 0x23, 0x11, 0x06, 0x28, 0x1A, 0x4C, - 0x6B, 0x6D, 0x1B, 0x06, 0x1D, 0x6D, 0x60, 0x1A, 0x70, 0x1B, 0x01, 0x01, - 0x11, 0x06, 0x03, 0x63, 0x1A, 0x70, 0x01, 0x04, 0x50, 0x6B, 0x4A, 0x1C, - 0x06, 0x03, 0x5F, 0x04, 0x01, 0x7B, 0x51, 0x51, 0x04, 0x60, 0x51, 0x51, - 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x38, 0x1D, 0x1A, 0x51, 0x6D, - 0x60, 0x06, 0x80, 0x63, 0x75, 0x1C, 0x06, 0x06, 0x01, 0x02, 0x3B, 0x04, - 0x80, 0x57, 0x76, 0x1C, 0x06, 0x06, 0x01, 0x03, 0x3B, 0x04, 0x80, 0x4D, - 0x77, 0x1C, 0x06, 0x06, 0x01, 0x04, 0x3B, 0x04, 0x80, 0x43, 0x78, 0x1C, - 0x06, 0x05, 0x01, 0x05, 0x3B, 0x04, 0x3A, 0x79, 0x1C, 0x06, 0x05, 0x01, - 0x06, 0x3B, 0x04, 0x31, 0x55, 0x1C, 0x06, 0x05, 0x01, 0x02, 0x3A, 0x04, - 0x28, 0x56, 0x1C, 0x06, 0x05, 0x01, 0x03, 0x3A, 0x04, 0x1F, 0x57, 0x1C, - 0x06, 0x05, 0x01, 0x04, 0x3A, 0x04, 0x16, 0x58, 0x1C, 0x06, 0x05, 0x01, - 0x05, 0x3A, 0x04, 0x0D, 0x59, 0x1C, 0x06, 0x05, 0x01, 0x06, 0x3A, 0x04, - 0x04, 0x01, 0x00, 0x01, 0x00, 0x04, 0x04, 0x01, 0x00, 0x01, 0x00, 0x46, - 0x25, 0x45, 0x25, 0x7A, 0x61, 0x7A, 0x51, 0x1A, 0x01, 0x01, 0x3D, 0x25, - 0x73, 0x30, 0x1D, 0x00, 0x00, 0x01, 0x81, 0x06, 0x00, 0x01, 0x54, 0x0D, - 0x06, 0x02, 0x32, 0x1D, 0x1B, 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, - 0x6D, 0x71, 0x1B, 0x01, 0x01, 0x11, 0x06, 0x08, 0x63, 0x01, 0x01, 0x15, - 0x3E, 0x25, 0x04, 0x01, 0x2B, 0x7A, 0x00, 0x00, 0x70, 0x01, 0x06, 0x50, - 0x6F, 0x00, 0x00, 0x70, 0x01, 0x03, 0x50, 0x6B, 0x72, 0x06, 0x02, 0x37, - 0x1D, 0x00, 0x00, 0x26, 0x1B, 0x06, 0x07, 0x21, 0x1B, 0x06, 0x01, 0x16, - 0x04, 0x76, 0x2B, 0x00, 0x00, 0x01, 0x01, 0x50, 0x6A, 0x01, 0x01, 0x10, - 0x06, 0x02, 0x2C, 0x1D, 0x72, 0x27, 0x00, 0x00, 0x60, 0x05, 0x02, 0x39, - 0x1D, 0x47, 0x1C, 0x06, 0x04, 0x01, 0x17, 0x04, 0x12, 0x48, 0x1C, 0x06, - 0x04, 0x01, 0x18, 0x04, 0x0A, 0x49, 0x1C, 0x06, 0x04, 0x01, 0x19, 0x04, - 0x02, 0x39, 0x1D, 0x00, 0x04, 0x70, 0x1B, 0x01, 0x17, 0x01, 0x18, 0x4B, - 0x05, 0x02, 0x2F, 0x1D, 0x01, 0x18, 0x11, 0x03, 0x00, 0x4D, 0x6B, 0x66, - 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, 0x64, 0x08, 0x03, 0x01, 0x66, 0x02, - 0x01, 0x09, 0x04, 0x0E, 0x1B, 0x01, 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80, - 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, 0x03, 0x01, 0x02, 0x01, 0x01, 0x82, - 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02, - 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01, - 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01, - 0x01, 0x01, 0x0C, 0x67, 0x2A, 0x01, 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, - 0x07, 0x28, 0x02, 0x01, 0x01, 0x80, 0x64, 0x07, 0x27, 0x02, 0x01, 0x01, - 0x83, 0x10, 0x07, 0x28, 0x1F, 0x15, 0x06, 0x03, 0x01, 0x18, 0x09, 0x5D, - 0x09, 0x52, 0x1B, 0x01, 0x05, 0x14, 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, - 0x1F, 0x15, 0x01, 0x01, 0x26, 0x67, 0x02, 0x03, 0x09, 0x2A, 0x03, 0x03, - 0x01, 0x00, 0x01, 0x17, 0x67, 0x01, 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, - 0x00, 0x01, 0x3B, 0x67, 0x01, 0x3C, 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, - 0x01, 0x00, 0x01, 0x3C, 0x67, 0x02, 0x02, 0x09, 0x03, 0x02, 0x72, 0x1B, - 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x1A, 0x72, 0x1B, 0x01, 0x30, 0x01, 0x39, - 0x4B, 0x06, 0x03, 0x1A, 0x04, 0x74, 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, - 0x2F, 0x1D, 0x51, 0x02, 0x03, 0x02, 0x02, 0x00, 0x01, 0x72, 0x53, 0x01, - 0x0A, 0x08, 0x03, 0x00, 0x72, 0x53, 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, - 0x00, 0x03, 0x01, 0x66, 0x1B, 0x02, 0x01, 0x02, 0x00, 0x4B, 0x05, 0x02, - 0x2F, 0x1D, 0x00, 0x00, 0x23, 0x70, 0x01, 0x02, 0x50, 0x0B, 0x69, 0x00, - 0x03, 0x1B, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x6B, 0x72, 0x1B, 0x01, - 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x1B, 0x01, 0x00, 0x11, 0x06, - 0x0B, 0x1A, 0x1B, 0x05, 0x04, 0x1A, 0x01, 0x00, 0x00, 0x72, 0x04, 0x6F, - 0x02, 0x01, 0x1B, 0x05, 0x02, 0x33, 0x1D, 0x2A, 0x03, 0x01, 0x02, 0x02, - 0x25, 0x02, 0x02, 0x29, 0x03, 0x02, 0x1B, 0x06, 0x03, 0x72, 0x04, 0x68, - 0x1A, 0x02, 0x00, 0x02, 0x01, 0x0A, 0x00, 0x01, 0x72, 0x1B, 0x01, 0x81, - 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, 0x81, 0x00, 0x0A, 0x1B, 0x05, 0x02, - 0x31, 0x1D, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, - 0x19, 0x02, 0x00, 0x2A, 0x03, 0x00, 0x1B, 0x01, 0x83, 0xFF, 0xFF, 0x7F, - 0x12, 0x06, 0x02, 0x32, 0x1D, 0x01, 0x08, 0x0E, 0x26, 0x72, 0x23, 0x09, - 0x04, 0x60, 0x00, 0x00, 0x6A, 0x5E, 0x00, 0x00, 0x6B, 0x7A, 0x00, 0x00, - 0x70, 0x4E, 0x6B, 0x00, 0x01, 0x6B, 0x1B, 0x05, 0x02, 0x36, 0x1D, 0x72, - 0x1B, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x36, 0x1D, 0x03, 0x00, 0x1B, - 0x06, 0x16, 0x72, 0x02, 0x00, 0x1B, 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, - 0x06, 0x02, 0x36, 0x1D, 0x01, 0x08, 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, - 0x1A, 0x02, 0x00, 0x00, 0x00, 0x6B, 0x1B, 0x01, 0x81, 0x7F, 0x12, 0x06, - 0x08, 0x7A, 0x01, 0x00, 0x44, 0x25, 0x01, 0x00, 0x00, 0x1B, 0x44, 0x25, - 0x44, 0x29, 0x62, 0x01, 0x7F, 0x00, 0x01, 0x72, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x05, 0x14, 0x01, 0x01, 0x15, 0x1E, 0x02, 0x00, 0x01, 0x06, 0x14, - 0x1B, 0x01, 0x01, 0x15, 0x06, 0x02, 0x2D, 0x1D, 0x01, 0x04, 0x0E, 0x02, - 0x00, 0x01, 0x1F, 0x15, 0x1B, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x2E, 0x1D, - 0x09, 0x00, 0x00, 0x1B, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0x70, - 0x00, 0x00, 0x1B, 0x05, 0x02, 0x32, 0x1D, 0x2A, 0x73, 0x00, 0x00, 0x22, - 0x1B, 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x1A, 0x16, 0x04, 0x74, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, - 0x01, 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, - 0x7B, 0x1A, 0x00, 0x00, 0x1B, 0x06, 0x07, 0x7C, 0x1B, 0x06, 0x01, 0x16, - 0x04, 0x76, 0x00, 0x00, 0x01, 0x00, 0x20, 0x21, 0x0B, 0x2B, 0x00 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 15, - 20, - 24, - 28, - 32, - 36, - 40, - 44, - 48, - 52, - 56, - 60, - 64, - 68, - 72, - 76, - 80, - 84, - 88, - 93, - 98, - 103, - 111, - 116, - 121, - 126, - 131, - 136, - 141, - 146, - 151, - 156, - 161, - 166, - 181, - 187, - 193, - 198, - 206, - 214, - 220, - 231, - 246, - 250, - 255, - 260, - 265, - 270, - 275, - 279, - 289, - 620, - 625, - 639, - 659, - 666, - 678, - 692, - 707, - 740, - 960, - 974, - 991, - 1000, - 1067, - 1123, - 1127, - 1131, - 1136, - 1184, - 1210, - 1254, - 1265, - 1274, - 1287, - 1291, - 1295, - 1299, - 1303, - 1307, - 1311, - 1315, - 1327 -}; - -#define T0_INTERPRETED 39 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_x509_decoder_init_main, 92) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_x509_decoder_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* %25 */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSHi(a % b); - - } - break; - case 8: { - /* * */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a * b); - - } - break; - case 9: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 10: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 11: { - /* -rot */ - T0_NROT(); - } - break; - case 12: { - /* / */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSHi(a / b); - - } - break; - case 13: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 14: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 15: { - /* <= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a <= b)); - - } - break; - case 16: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 17: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 18: { - /* > */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a > b)); - - } - break; - case 19: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 20: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 21: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 22: { - /* co */ - T0_CO(); - } - break; - case 23: { - /* copy-ec-pkey */ - - size_t qlen = T0_POP(); - uint32_t curve = T0_POP(); - CTX->pkey.key_type = BR_KEYTYPE_EC; - CTX->pkey.key.ec.curve = curve; - CTX->pkey.key.ec.q = CTX->pkey_data; - CTX->pkey.key.ec.qlen = qlen; - - } - break; - case 24: { - /* copy-rsa-pkey */ - - size_t elen = T0_POP(); - size_t nlen = T0_POP(); - CTX->pkey.key_type = BR_KEYTYPE_RSA; - CTX->pkey.key.rsa.n = CTX->pkey_data; - CTX->pkey.key.rsa.nlen = nlen; - CTX->pkey.key.rsa.e = CTX->pkey_data + nlen; - CTX->pkey.key.rsa.elen = elen; - - } - break; - case 25: { - /* data-get8 */ - - size_t addr = T0_POP(); - T0_PUSH(t0_datablock[addr]); - - } - break; - case 26: { - /* drop */ - (void)T0_POP(); - } - break; - case 27: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 28: { - /* eqOID */ - - const unsigned char *a2 = &t0_datablock[T0_POP()]; - const unsigned char *a1 = &CTX->pad[0]; - size_t len = a1[0]; - int x; - if (len == a2[0]) { - x = -(memcmp(a1 + 1, a2 + 1, len) == 0); - } else { - x = 0; - } - T0_PUSH((uint32_t)x); - - } - break; - case 29: { - /* fail */ - - CTX->err = T0_POPi(); - T0_CO(); - - } - break; - case 30: { - /* neg */ - - uint32_t a = T0_POP(); - T0_PUSH(-a); - - } - break; - case 31: { - /* or */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a | b); - - } - break; - case 32: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 33: { - /* read-blob-inner */ - - uint32_t len = T0_POP(); - uint32_t addr = T0_POP(); - size_t clen = CTX->hlen; - if (clen > len) { - clen = (size_t)len; - } - if (addr != 0) { - memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); - } - if (CTX->copy_dn && CTX->append_dn) { - CTX->append_dn(CTX->append_dn_ctx, CTX->hbuf, clen); - } - CTX->hbuf += clen; - CTX->hlen -= clen; - T0_PUSH(addr + clen); - T0_PUSH(len - clen); - - } - break; - case 34: { - /* read8-low */ - - if (CTX->hlen == 0) { - T0_PUSHi(-1); - } else { - unsigned char x = *CTX->hbuf ++; - if (CTX->copy_dn && CTX->append_dn) { - CTX->append_dn(CTX->append_dn_ctx, &x, 1); - } - CTX->hlen --; - T0_PUSH(x); - } - - } - break; - case 35: { - /* rot */ - T0_ROT(); - } - break; - case 36: { - /* set32 */ - - uint32_t addr = T0_POP(); - *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); - - } - break; - case 37: { - /* set8 */ - - uint32_t addr = T0_POP(); - *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); - - } - break; - case 38: { - /* swap */ - T0_SWAP(); - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/x509_knownkey.c b/src/tls/bearssl/x509_knownkey.c deleted file mode 100644 index 0587f8a5c..000000000 --- a/src/tls/bearssl/x509_knownkey.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_x509.h */ -void -br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx, - const br_rsa_public_key *pk, unsigned usages) -{ - ctx->vtable = &br_x509_knownkey_vtable; - ctx->pkey.key_type = BR_KEYTYPE_RSA; - ctx->pkey.key.rsa = *pk; - ctx->usages = usages; -} - -/* see bearssl_x509.h */ -void -br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, - const br_ec_public_key *pk, unsigned usages) -{ - ctx->vtable = &br_x509_knownkey_vtable; - ctx->pkey.key_type = BR_KEYTYPE_EC; - ctx->pkey.key.ec = *pk; - ctx->usages = usages; -} - -static void -kk_start_chain(const br_x509_class **ctx, const char *server_name) -{ - (void)ctx; - (void)server_name; -} - -static void -kk_start_cert(const br_x509_class **ctx, uint32_t length) -{ - (void)ctx; - (void)length; -} - -static void -kk_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) -{ - (void)ctx; - (void)buf; - (void)len; -} - -static void -kk_end_cert(const br_x509_class **ctx) -{ - (void)ctx; -} - -static unsigned -kk_end_chain(const br_x509_class **ctx) -{ - (void)ctx; - return 0; -} - -static const br_x509_pkey * -kk_get_pkey(const br_x509_class *const *ctx, unsigned *usages) -{ - const br_x509_knownkey_context *xc; - - xc = (const br_x509_knownkey_context *)ctx; - if (usages != NULL) { - *usages = xc->usages; - } - return &xc->pkey; -} - -/* see bearssl_x509.h */ -const br_x509_class br_x509_knownkey_vtable = { - sizeof(br_x509_knownkey_context), - kk_start_chain, - kk_start_cert, - kk_append, - kk_end_cert, - kk_end_chain, - kk_get_pkey -}; - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/x509_minimal.c b/src/tls/bearssl/x509_minimal.c deleted file mode 100644 index 7fb35e728..000000000 --- a/src/tls/bearssl/x509_minimal.c +++ /dev/null @@ -1,1718 +0,0 @@ -/* Automatically generated code; do not modify directly. */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include -#include - -typedef struct { - uint32_t *dp; - uint32_t *rp; - const unsigned char *ip; -} t0_context; - -static uint32_t -t0_parse7E_unsigned(const unsigned char **p) -{ - uint32_t x; - - x = 0; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - return x; - } - } -} - -static int32_t -t0_parse7E_signed(const unsigned char **p) -{ - int neg; - uint32_t x; - - neg = ((**p) >> 6) & 1; - x = (uint32_t)-neg; - for (;;) { - unsigned y; - - y = *(*p) ++; - x = (x << 7) | (uint32_t)(y & 0x7F); - if (y < 0x80) { - if (neg) { - return -(int32_t)~x - 1; - } else { - return (int32_t)x; - } - } - } -} - -#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80) -#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F) -#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8) -#define T0_INT1(x) T0_FBYTE(x, 0) -#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) -#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0) - -/* static const unsigned char t0_datablock[]; */ - - -void br_x509_minimal_init_main(void *t0ctx); - -void br_x509_minimal_run(void *t0ctx); - - - -#include "inner.h" - - - - - -#include "inner.h" - -/* - * Implementation Notes - * -------------------- - * - * The C code pushes the data by chunks; all decoding is done in the - * T0 code. The cert_length value is set to the certificate length when - * a new certificate is started; the T0 code picks it up as outer limit, - * and decoding functions use it to ensure that no attempt is made at - * reading past it. The T0 code also checks that once the certificate is - * decoded, there are no trailing bytes. - * - * The T0 code sets cert_length to 0 when the certificate is fully - * decoded. - * - * The C code must still perform two checks: - * - * -- If the certificate length is 0, then the T0 code will not be - * invoked at all. This invalid condition must thus be reported by the - * C code. - * - * -- When reaching the end of certificate, the C code must verify that - * the certificate length has been set to 0, thereby signaling that - * the T0 code properly decoded a certificate. - * - * Processing of a chain works in the following way: - * - * -- The error flag is set to a non-zero value when validation is - * finished. The value is either BR_ERR_X509_OK (validation is - * successful) or another non-zero error code. When a non-zero error - * code is obtained, the remaining bytes in the current certificate and - * the subsequent certificates (if any) are completely ignored. - * - * -- Each certificate is decoded in due course, with the following - * "interesting points": - * - * -- Start of the TBS: the multihash engine is reset and activated. - * - * -- Start of the issuer DN: the secondary hash engine is started, - * to process the encoded issuer DN. - * - * -- End of the issuer DN: the secondary hash engine is stopped. The - * resulting hash value is computed and then copied into the - * next_dn_hash[] buffer. - * - * -- Start of the subject DN: the secondary hash engine is started, - * to process the encoded subject DN. - * - * -- For the EE certificate only: the Common Name, if any, is matched - * against the expected server name. - * - * -- End of the subject DN: the secondary hash engine is stopped. The - * resulting hash value is computed into the pad. It is then processed: - * - * -- If this is the EE certificate, then the hash is ignored - * (except for direct trust processing, see later; the hash is - * simply left in current_dn_hash[]). - * - * -- Otherwise, the hashed subject DN is compared with the saved - * hash value (in saved_dn_hash[]). They must match. - * - * Either way, the next_dn_hash[] value is then copied into the - * saved_dn_hash[] value. Thus, at that point, saved_dn_hash[] - * contains the hash of the issuer DN for the current certificate, - * and current_dn_hash[] contains the hash of the subject DN for the - * current certificate. - * - * -- Public key: it is decoded into the cert_pkey[] buffer. Unknown - * key types are reported at that point. - * - * -- If this is the EE certificate, then the key type is compared - * with the expected key type (initialization parameter). The public - * key data is copied to ee_pkey_data[]. The key and hashed subject - * DN are also compared with the "direct trust" keys; if the key - * and DN are matched, then validation ends with a success. - * - * -- Otherwise, the saved signature (cert_sig[]) is verified - * against the saved TBS hash (tbs_hash[]) and that freshly - * decoded public key. Failure here ends validation with an error. - * - * -- Extensions: extension values are processed in due order. - * - * -- Basic Constraints: for all certificates except EE, must be - * present, indicate a CA, and have a path length compatible with - * the chain length so far. - * - * -- Key Usage: for the EE, if present, must allow signatures - * or encryption/key exchange, as required for the cipher suite. - * For non-EE, if present, must have the "certificate sign" bit. - * - * -- Subject Alt Name: for the EE, dNSName names are matched - * against the server name. Ignored for non-EE. - * - * -- Authority Key Identifier, Subject Key Identifier, Issuer - * Alt Name, Subject Directory Attributes, CRL Distribution Points - * Freshest CRL, Authority Info Access and Subject Info Access - * extensions are always ignored: they either contain only - * informative data, or they relate to revocation processing, which - * we explicitly do not support. - * - * -- All other extensions are ignored if non-critical. If a - * critical extension other than the ones above is encountered, - * then a failure is reported. - * - * -- End of the TBS: the multihash engine is stopped. - * - * -- Signature algorithm: the signature algorithm on the - * certificate is decoded. A failure is reported if that algorithm - * is unknown. The hashed TBS corresponding to the signature hash - * function is computed and stored in tbs_hash[] (if not supported, - * then a failure is reported). The hash OID and length are stored - * in cert_sig_hash_oid and cert_sig_hash_len. - * - * -- Signature value: the signature value is copied into the - * cert_sig[] array. - * - * -- Certificate end: the hashed issuer DN (saved_dn_hash[]) is - * looked up in the trust store (CA trust anchors only); for all - * that match, the signature (cert_sig[]) is verified against the - * anchor public key (hashed TBS is in tbs_hash[]). If one of these - * signatures is valid, then validation ends with a success. - * - * -- If the chain end is reached without obtaining a validation success, - * then validation is reported as failed. - */ - -#if BR_USE_UNIX_TIME -#include -#endif - -#if BR_USE_WIN32_TIME -#include -#endif - -/* - * The T0 compiler will produce these prototypes declarations in the - * header. - * -void br_x509_minimal_init_main(void *ctx); -void br_x509_minimal_run(void *ctx); - */ - -/* see bearssl_x509.h */ -void -br_x509_minimal_init(br_x509_minimal_context *ctx, - const br_hash_class *dn_hash_impl, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) -{ - memset(ctx, 0, sizeof *ctx); - ctx->vtable = &br_x509_minimal_vtable; - ctx->dn_hash_impl = dn_hash_impl; - ctx->trust_anchors = trust_anchors; - ctx->trust_anchors_num = trust_anchors_num; -} - -static void -xm_start_chain(const br_x509_class **ctx, const char *server_name) -{ - br_x509_minimal_context *cc; - size_t u; - - cc = (br_x509_minimal_context *)(void *)ctx; - for (u = 0; u < cc->num_name_elts; u ++) { - cc->name_elts[u].status = 0; - cc->name_elts[u].buf[0] = 0; - } - memset(&cc->pkey, 0, sizeof cc->pkey); - cc->num_certs = 0; - cc->err = 0; - cc->cpu.dp = cc->dp_stack; - cc->cpu.rp = cc->rp_stack; - br_x509_minimal_init_main(&cc->cpu); - if (server_name == NULL || *server_name == 0) { - cc->server_name = NULL; - } else { - cc->server_name = server_name; - } -} - -static void -xm_start_cert(const br_x509_class **ctx, uint32_t length) -{ - br_x509_minimal_context *cc; - - cc = (br_x509_minimal_context *)(void *)ctx; - if (cc->err != 0) { - return; - } - if (length == 0) { - cc->err = BR_ERR_X509_TRUNCATED; - return; - } - cc->cert_length = length; -} - -static void -xm_append(const br_x509_class **ctx, const unsigned char *buf, size_t len) -{ - br_x509_minimal_context *cc; - - cc = (br_x509_minimal_context *)(void *)ctx; - if (cc->err != 0) { - return; - } - cc->hbuf = buf; - cc->hlen = len; - br_x509_minimal_run(&cc->cpu); -} - -static void -xm_end_cert(const br_x509_class **ctx) -{ - br_x509_minimal_context *cc; - - cc = (br_x509_minimal_context *)(void *)ctx; - if (cc->err == 0 && cc->cert_length != 0) { - cc->err = BR_ERR_X509_TRUNCATED; - } - cc->num_certs ++; -} - -static unsigned -xm_end_chain(const br_x509_class **ctx) -{ - br_x509_minimal_context *cc; - - cc = (br_x509_minimal_context *)(void *)ctx; - if (cc->err == 0) { - if (cc->num_certs == 0) { - cc->err = BR_ERR_X509_EMPTY_CHAIN; - } else { - cc->err = BR_ERR_X509_NOT_TRUSTED; - } - } else if (cc->err == BR_ERR_X509_OK) { - return 0; - } - return (unsigned)cc->err; -} - -static const br_x509_pkey * -xm_get_pkey(const br_x509_class *const *ctx, unsigned *usages) -{ - br_x509_minimal_context *cc; - - cc = (br_x509_minimal_context *)(void *)ctx; - if (cc->err == BR_ERR_X509_OK - || cc->err == BR_ERR_X509_NOT_TRUSTED) - { - if (usages != NULL) { - *usages = cc->key_usages; - } - return &((br_x509_minimal_context *)(void *)ctx)->pkey; - } else { - return NULL; - } -} - -/* see bearssl_x509.h */ -const br_x509_class br_x509_minimal_vtable = { - sizeof(br_x509_minimal_context), - xm_start_chain, - xm_start_cert, - xm_append, - xm_end_cert, - xm_end_chain, - xm_get_pkey -}; - -#define CTX ((br_x509_minimal_context *)(void *)((unsigned char *)t0ctx - offsetof(br_x509_minimal_context, cpu))) -#define CONTEXT_NAME br_x509_minimal_context - -#define DNHASH_LEN ((CTX->dn_hash_impl->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK) - -/* - * Hash a DN (from a trust anchor) into the provided buffer. This uses the - * DN hash implementation and context structure from the X.509 engine - * context. - */ -static void -hash_dn(br_x509_minimal_context *ctx, const void *dn, size_t len, - unsigned char *out) -{ - ctx->dn_hash_impl->init(&ctx->dn_hash.vtable); - ctx->dn_hash_impl->update(&ctx->dn_hash.vtable, dn, len); - ctx->dn_hash_impl->out(&ctx->dn_hash.vtable, out); -} - -/* - * Compare two big integers for equality. The integers use unsigned big-endian - * encoding; extra leading bytes (of value 0) are allowed. - */ -static int -eqbigint(const unsigned char *b1, size_t len1, - const unsigned char *b2, size_t len2) -{ - while (len1 > 0 && *b1 == 0) { - b1 ++; - len1 --; - } - while (len2 > 0 && *b2 == 0) { - b2 ++; - len2 --; - } - if (len1 != len2) { - return 0; - } - return memcmp(b1, b2, len1) == 0; -} - -/* - * Compare two strings for equality, in a case-insensitive way. This - * function handles casing only for ASCII letters. - */ -static int -eqnocase(const void *s1, const void *s2, size_t len) -{ - const unsigned char *buf1, *buf2; - - buf1 = s1; - buf2 = s2; - while (len -- > 0) { - int x1, x2; - - x1 = *buf1 ++; - x2 = *buf2 ++; - if (x1 >= 'A' && x1 <= 'Z') { - x1 += 'a' - 'A'; - } - if (x2 >= 'A' && x2 <= 'Z') { - x2 += 'a' - 'A'; - } - if (x1 != x2) { - return 0; - } - } - return 1; -} - -static int verify_signature(br_x509_minimal_context *ctx, - const br_x509_pkey *pk); - - - -static const unsigned char t0_datablock[] = { - 0x00, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x09, 0x2A, 0x86, - 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0E, 0x09, 0x2A, 0x86, 0x48, 0x86, - 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, - 0x01, 0x01, 0x0C, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, - 0x0D, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x09, 0x60, 0x86, 0x48, 0x01, - 0x65, 0x03, 0x04, 0x02, 0x04, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, - 0x04, 0x02, 0x01, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x02, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x07, - 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x08, 0x2A, 0x86, 0x48, 0xCE, - 0x3D, 0x03, 0x01, 0x07, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x05, 0x2B, - 0x81, 0x04, 0x00, 0x23, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01, - 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01, 0x08, 0x2A, 0x86, - 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, - 0x04, 0x03, 0x03, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04, - 0x03, 0x55, 0x04, 0x03, 0x00, 0x1F, 0x03, 0xFC, 0x07, 0x7F, 0x0B, 0x5E, - 0x0F, 0x1F, 0x12, 0xFE, 0x16, 0xBF, 0x1A, 0x9F, 0x1E, 0x7E, 0x22, 0x3F, - 0x26, 0x1E, 0x29, 0xDF, 0x00, 0x1F, 0x03, 0xFD, 0x07, 0x9F, 0x0B, 0x7E, - 0x0F, 0x3F, 0x13, 0x1E, 0x16, 0xDF, 0x1A, 0xBF, 0x1E, 0x9E, 0x22, 0x5F, - 0x26, 0x3E, 0x29, 0xFF, 0x03, 0x55, 0x1D, 0x13, 0x03, 0x55, 0x1D, 0x0F, - 0x03, 0x55, 0x1D, 0x11, 0x03, 0x55, 0x1D, 0x20, 0x08, 0x2B, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x02, 0x01, 0x03, 0x55, 0x1D, 0x23, 0x03, 0x55, 0x1D, - 0x0E, 0x03, 0x55, 0x1D, 0x12, 0x03, 0x55, 0x1D, 0x09, 0x03, 0x55, 0x1D, - 0x1F, 0x03, 0x55, 0x1D, 0x2E, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, - 0x01, 0x01, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0B -}; - -static const unsigned char t0_codeblock[] = { - 0x00, 0x01, 0x00, 0x0D, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x01, - 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x09, 0x00, 0x00, 0x01, 0x01, 0x0A, - 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_BOOLEAN), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_DN), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_SERVER_NAME), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TAG_CLASS), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TAG_VALUE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_BAD_TIME), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_CRITICAL_EXTENSION), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_DN_MISMATCH), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_EXPIRED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_EXTRA_ELEMENT), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_FORBIDDEN_KEY_USAGE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INDEFINITE_LENGTH), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_INNER_TRUNC), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_LIMIT_EXCEEDED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_CA), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_CONSTRUCTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_NOT_PRIMITIVE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_OVERFLOW), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_PARTIAL_BYTE), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNEXPECTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_UNSUPPORTED), 0x00, 0x00, 0x01, - T0_INT1(BR_ERR_X509_WEAK_PUBLIC_KEY), 0x00, 0x00, 0x01, - T0_INT1(BR_KEYTYPE_EC), 0x00, 0x00, 0x01, T0_INT1(BR_KEYTYPE_RSA), - 0x00, 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_length)), 0x00, - 0x00, 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_len)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_hash_oid)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, cert_sig_len)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, cert_signer_key_type)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, current_dn_hash)), 0x00, 0x00, - 0x01, T0_INT2(offsetof(CONTEXT_NAME, key_usages)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(br_x509_minimal_context, pkey_data)), 0x01, - T0_INT2(BR_X509_BUFSIZE_KEY), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, min_rsa_size)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, next_dn_hash)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, num_certs)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, pad)), 0x00, 0x00, 0x01, - T0_INT2(offsetof(CONTEXT_NAME, saved_dn_hash)), 0x00, 0x00, 0xC9, 0x71, - 0x00, 0x00, 0x01, 0x80, 0x73, 0x00, 0x00, 0x01, 0x80, 0x7C, 0x00, 0x00, - 0x01, 0x81, 0x02, 0x00, 0x00, 0x92, 0x05, 0x05, 0x34, 0x42, 0x01, 0x00, - 0x00, 0x34, 0x01, 0x0A, 0x0E, 0x09, 0x01, 0x9A, 0xFF, 0xB8, 0x00, 0x0A, - 0x00, 0x00, 0x01, 0x82, 0x19, 0x00, 0x00, 0x01, 0x82, 0x01, 0x00, 0x00, - 0x01, 0x81, 0x68, 0x00, 0x04, 0x03, 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x02, 0x01, 0x11, 0x06, 0x07, 0x02, 0x02, 0x02, 0x00, - 0x0D, 0x04, 0x05, 0x02, 0x03, 0x02, 0x01, 0x0D, 0x00, 0x02, 0x03, 0x00, - 0x03, 0x01, 0x25, 0x02, 0x01, 0x13, 0x3B, 0x02, 0x00, 0x0F, 0x15, 0x00, - 0x00, 0x01, 0x81, 0x74, 0x00, 0x00, 0x05, 0x02, 0x52, 0x28, 0x00, 0x00, - 0x06, 0x02, 0x53, 0x28, 0x00, 0x00, 0x01, 0x10, 0x77, 0x00, 0x00, 0x11, - 0x05, 0x02, 0x56, 0x28, 0x74, 0x00, 0x00, 0x11, 0x05, 0x02, 0x56, 0x28, - 0x75, 0x00, 0x00, 0x06, 0x02, 0x4C, 0x28, 0x00, 0x00, 0x01, 0x82, 0x11, - 0x00, 0x00, 0x25, 0x20, 0x01, 0x08, 0x0E, 0x3B, 0x40, 0x20, 0x09, 0x00, - 0x09, 0x03, 0x00, 0x5B, 0x2B, 0xAF, 0x39, 0xAF, 0xB3, 0x25, 0x01, 0x20, - 0x11, 0x06, 0x11, 0x24, 0x74, 0xAD, 0xB3, 0x01, 0x02, 0x78, 0xB0, 0x01, - 0x02, 0x12, 0x06, 0x02, 0x57, 0x28, 0x79, 0xB3, 0x01, 0x02, 0x78, 0xAE, - 0xAF, 0xC2, 0x9C, 0x65, 0x61, 0x21, 0x16, 0xAF, 0xA7, 0x29, 0x69, 0x06, - 0x02, 0x4B, 0x28, 0xA7, 0x29, 0x71, 0x06, 0x02, 0x4B, 0x28, 0x79, 0x02, - 0x00, 0x06, 0x05, 0x9D, 0x03, 0x01, 0x04, 0x09, 0x9C, 0x61, 0x68, 0x21, - 0x27, 0x05, 0x02, 0x4A, 0x28, 0x68, 0x65, 0x21, 0x16, 0xAF, 0xAF, 0x9E, - 0x05, 0x02, 0x57, 0x28, 0xBC, 0x26, 0x06, 0x27, 0xC2, 0xA4, 0xAF, 0x63, - 0xAA, 0x03, 0x03, 0x63, 0x3B, 0x02, 0x03, 0x09, 0x3B, 0x02, 0x03, 0x0A, - 0xAA, 0x03, 0x04, 0x79, 0x64, 0x2A, 0x01, 0x81, 0x00, 0x09, 0x02, 0x03, - 0x12, 0x06, 0x02, 0x58, 0x28, 0x79, 0x5A, 0x03, 0x02, 0x04, 0x3A, 0x88, - 0x26, 0x06, 0x34, 0x9E, 0x05, 0x02, 0x57, 0x28, 0x6A, 0x26, 0x06, 0x04, - 0x01, 0x17, 0x04, 0x12, 0x6B, 0x26, 0x06, 0x04, 0x01, 0x18, 0x04, 0x0A, - 0x6C, 0x26, 0x06, 0x04, 0x01, 0x19, 0x04, 0x02, 0x57, 0x28, 0x03, 0x05, - 0x79, 0xA4, 0x25, 0x03, 0x06, 0x25, 0x63, 0x34, 0x0D, 0x06, 0x02, 0x50, - 0x28, 0xA5, 0x59, 0x03, 0x02, 0x04, 0x02, 0x57, 0x28, 0x79, 0x02, 0x00, - 0x06, 0x21, 0x02, 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03, - 0x02, 0x04, 0x1D, 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, - 0x05, 0x02, 0x06, 0x1C, 0x04, 0x03, 0x57, 0x28, 0x24, 0x04, 0x24, 0x02, - 0x02, 0x5A, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x03, 0x02, 0x04, 0x23, - 0x04, 0x10, 0x59, 0x30, 0x11, 0x06, 0x08, 0x24, 0x02, 0x05, 0x02, 0x06, - 0x22, 0x04, 0x03, 0x57, 0x28, 0x24, 0x25, 0x06, 0x01, 0x28, 0x24, 0x01, - 0x00, 0x03, 0x07, 0xB4, 0x01, 0x21, 0x8F, 0x01, 0x22, 0x8F, 0x25, 0x01, - 0x23, 0x11, 0x06, 0x81, 0x26, 0x24, 0x74, 0xAD, 0xAF, 0x25, 0x06, 0x81, - 0x1A, 0x01, 0x00, 0x03, 0x08, 0xAF, 0x9E, 0x24, 0xB3, 0x25, 0x01, 0x01, - 0x11, 0x06, 0x04, 0xA6, 0x03, 0x08, 0xB3, 0x01, 0x04, 0x78, 0xAD, 0x70, - 0x26, 0x06, 0x0F, 0x02, 0x00, 0x06, 0x03, 0xC3, 0x04, 0x05, 0x99, 0x01, - 0x7F, 0x03, 0x07, 0x04, 0x80, 0x6C, 0x91, 0x26, 0x06, 0x06, 0x02, 0x00, - 0x9B, 0x04, 0x80, 0x62, 0xC5, 0x26, 0x06, 0x11, 0x02, 0x00, 0x06, 0x09, - 0x01, 0x00, 0x03, 0x01, 0x98, 0x03, 0x01, 0x04, 0x01, 0xC3, 0x04, 0x80, - 0x4D, 0x73, 0x26, 0x06, 0x0A, 0x02, 0x08, 0x06, 0x03, 0x9A, 0x04, 0x01, - 0xC3, 0x04, 0x3F, 0x6F, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x38, 0xC8, 0x26, - 0x06, 0x03, 0xC3, 0x04, 0x31, 0x90, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x2A, - 0xC6, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x23, 0x7A, 0x26, 0x06, 0x03, 0xC3, - 0x04, 0x1C, 0x85, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x15, 0x6E, 0x26, 0x06, - 0x03, 0xC3, 0x04, 0x0E, 0xC7, 0x26, 0x06, 0x03, 0xC3, 0x04, 0x07, 0x02, - 0x08, 0x06, 0x02, 0x49, 0x28, 0xC3, 0x79, 0x79, 0x04, 0xFE, 0x62, 0x79, - 0x79, 0x04, 0x08, 0x01, 0x7F, 0x11, 0x05, 0x02, 0x56, 0x28, 0x24, 0x79, - 0x3A, 0x02, 0x00, 0x06, 0x08, 0x02, 0x01, 0x3C, 0x2F, 0x05, 0x02, 0x45, - 0x28, 0x02, 0x00, 0x06, 0x01, 0x17, 0x02, 0x00, 0x02, 0x07, 0x2F, 0x05, - 0x02, 0x51, 0x28, 0xB3, 0x76, 0xAD, 0x9E, 0x06, 0x80, 0x77, 0xBD, 0x26, - 0x06, 0x07, 0x01, 0x02, 0x5A, 0x8A, 0x04, 0x80, 0x5E, 0xBE, 0x26, 0x06, - 0x07, 0x01, 0x03, 0x5A, 0x8B, 0x04, 0x80, 0x53, 0xBF, 0x26, 0x06, 0x07, - 0x01, 0x04, 0x5A, 0x8C, 0x04, 0x80, 0x48, 0xC0, 0x26, 0x06, 0x06, 0x01, - 0x05, 0x5A, 0x8D, 0x04, 0x3E, 0xC1, 0x26, 0x06, 0x06, 0x01, 0x06, 0x5A, - 0x8E, 0x04, 0x34, 0x7F, 0x26, 0x06, 0x06, 0x01, 0x02, 0x59, 0x8A, 0x04, - 0x2A, 0x80, 0x26, 0x06, 0x06, 0x01, 0x03, 0x59, 0x8B, 0x04, 0x20, 0x81, - 0x26, 0x06, 0x06, 0x01, 0x04, 0x59, 0x8C, 0x04, 0x16, 0x82, 0x26, 0x06, - 0x06, 0x01, 0x05, 0x59, 0x8D, 0x04, 0x0C, 0x83, 0x26, 0x06, 0x06, 0x01, - 0x06, 0x59, 0x8E, 0x04, 0x02, 0x57, 0x28, 0x5E, 0x35, 0x60, 0x37, 0x1B, - 0x25, 0x05, 0x02, 0x57, 0x28, 0x5D, 0x37, 0x04, 0x02, 0x57, 0x28, 0xC2, - 0xA4, 0x25, 0x01, T0_INT2(BR_X509_BUFSIZE_SIG), 0x12, 0x06, 0x02, 0x50, - 0x28, 0x25, 0x5F, 0x35, 0x5C, 0xA5, 0x79, 0x79, 0x01, 0x00, 0x5B, 0x36, - 0x18, 0x00, 0x00, 0x01, 0x30, 0x0A, 0x25, 0x01, 0x00, 0x01, 0x09, 0x72, - 0x05, 0x02, 0x48, 0x28, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x01, 0x81, - 0x08, 0x00, 0x00, 0x01, 0x81, 0x10, 0x00, 0x00, 0x01, 0x81, 0x19, 0x00, - 0x00, 0x01, 0x81, 0x22, 0x00, 0x00, 0x01, 0x81, 0x2B, 0x00, 0x01, 0x7E, - 0x01, 0x01, 0x11, 0x3B, 0x01, 0x83, 0xFD, 0x7F, 0x11, 0x15, 0x06, 0x03, - 0x3B, 0x24, 0x00, 0x3B, 0x25, 0x03, 0x00, 0x25, 0xCA, 0x05, 0x04, 0x42, - 0x01, 0x00, 0x00, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x96, 0x04, - 0x80, 0x49, 0x25, 0x01, 0x90, 0x00, 0x0D, 0x06, 0x0F, 0x01, 0x06, 0x14, - 0x01, 0x81, 0x40, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x00, 0x97, 0x04, 0x33, - 0x25, 0x01, 0x83, 0xFF, 0x7F, 0x0D, 0x06, 0x14, 0x01, 0x0C, 0x14, 0x01, - 0x81, 0x60, 0x2F, 0x96, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00, 0x01, - 0x00, 0x97, 0x04, 0x17, 0x01, 0x12, 0x14, 0x01, 0x81, 0x70, 0x2F, 0x96, - 0x02, 0x00, 0x01, 0x0C, 0x97, 0x02, 0x00, 0x01, 0x06, 0x97, 0x02, 0x00, - 0x01, 0x00, 0x97, 0x00, 0x00, 0x01, 0x82, 0x15, 0x00, 0x00, 0x25, 0x01, - 0x83, 0xB0, 0x00, 0x01, 0x83, 0xB7, 0x7F, 0x72, 0x00, 0x00, 0x01, 0x81, - 0x34, 0x00, 0x00, 0x01, 0x80, 0x6B, 0x00, 0x00, 0x01, 0x81, 0x78, 0x00, - 0x00, 0x01, 0x3D, 0x00, 0x00, 0x01, 0x80, 0x43, 0x00, 0x00, 0x01, 0x80, - 0x4D, 0x00, 0x00, 0x01, 0x80, 0x57, 0x00, 0x00, 0x01, 0x80, 0x61, 0x00, - 0x00, 0x30, 0x11, 0x06, 0x04, 0x42, 0xAD, 0xC2, 0xB4, 0x00, 0x00, 0x01, - 0x82, 0x09, 0x00, 0x00, 0x01, 0x81, 0x6C, 0x00, 0x00, 0x25, 0x01, 0x83, - 0xB8, 0x00, 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x00, 0x00, 0x01, 0x30, 0x62, - 0x37, 0x01, 0x7F, 0x7C, 0x19, 0x01, 0x00, 0x7C, 0x19, 0x04, 0x7A, 0x00, - 0x01, 0x81, 0x38, 0x00, 0x01, 0x7E, 0x0D, 0x06, 0x02, 0x4F, 0x28, 0x25, - 0x03, 0x00, 0x0A, 0x02, 0x00, 0x00, 0x00, 0x30, 0x25, 0x3F, 0x3B, 0x01, - 0x82, 0x00, 0x13, 0x2F, 0x06, 0x04, 0x42, 0x01, 0x00, 0x00, 0x30, 0x67, - 0x09, 0x37, 0x40, 0x00, 0x00, 0x14, 0x01, 0x3F, 0x15, 0x01, 0x81, 0x00, - 0x2F, 0x96, 0x00, 0x02, 0x01, 0x00, 0x03, 0x00, 0xAF, 0x25, 0x06, 0x80, - 0x59, 0xB3, 0x01, 0x20, 0x30, 0x11, 0x06, 0x17, 0x24, 0x74, 0xAD, 0x9E, - 0x24, 0x01, 0x7F, 0x2E, 0x03, 0x01, 0xB3, 0x01, 0x20, 0x77, 0xAD, 0xB2, - 0x02, 0x01, 0x1F, 0x79, 0x79, 0x04, 0x38, 0x01, 0x21, 0x30, 0x11, 0x06, - 0x08, 0x24, 0x75, 0xB6, 0x01, 0x01, 0x1E, 0x04, 0x2A, 0x01, 0x22, 0x30, - 0x11, 0x06, 0x11, 0x24, 0x75, 0xB6, 0x25, 0x06, 0x06, 0x2C, 0x02, 0x00, - 0x2F, 0x03, 0x00, 0x01, 0x02, 0x1E, 0x04, 0x13, 0x01, 0x26, 0x30, 0x11, - 0x06, 0x08, 0x24, 0x75, 0xB6, 0x01, 0x06, 0x1E, 0x04, 0x05, 0x42, 0xAE, - 0x01, 0x00, 0x24, 0x04, 0xFF, 0x23, 0x79, 0x02, 0x00, 0x00, 0x00, 0xAF, - 0xB4, 0x25, 0x01, 0x01, 0x11, 0x06, 0x08, 0xA6, 0x05, 0x02, 0x51, 0x28, - 0xB4, 0x04, 0x02, 0x51, 0x28, 0x25, 0x01, 0x02, 0x11, 0x06, 0x0C, 0x24, - 0x75, 0xB0, 0x66, 0x2B, 0x41, 0x0D, 0x06, 0x02, 0x51, 0x28, 0xB4, 0x01, - 0x7F, 0x10, 0x06, 0x02, 0x56, 0x28, 0x24, 0x79, 0x00, 0x00, 0xAF, 0x25, - 0x06, 0x1A, 0xAF, 0x9E, 0x24, 0x25, 0x06, 0x11, 0xAF, 0x25, 0x06, 0x0C, - 0xAF, 0x9E, 0x24, 0x89, 0x26, 0x05, 0x02, 0x49, 0x28, 0xC2, 0x04, 0x71, - 0x79, 0x79, 0x04, 0x63, 0x79, 0x00, 0x02, 0x03, 0x00, 0xB3, 0x01, 0x03, - 0x78, 0xAD, 0xBA, 0x03, 0x01, 0x02, 0x01, 0x01, 0x07, 0x12, 0x06, 0x02, - 0x56, 0x28, 0x25, 0x01, 0x00, 0x30, 0x11, 0x06, 0x05, 0x24, 0x4D, 0x28, - 0x04, 0x15, 0x01, 0x01, 0x30, 0x11, 0x06, 0x0A, 0x24, 0xBA, 0x02, 0x01, - 0x14, 0x02, 0x01, 0x0E, 0x04, 0x05, 0x24, 0xBA, 0x01, 0x00, 0x24, 0x02, - 0x00, 0x06, 0x19, 0x01, 0x00, 0x30, 0x01, 0x38, 0x15, 0x06, 0x03, 0x01, - 0x10, 0x2F, 0x3B, 0x01, 0x81, 0x40, 0x15, 0x06, 0x03, 0x01, 0x20, 0x2F, - 0x62, 0x37, 0x04, 0x07, 0x01, 0x04, 0x15, 0x05, 0x02, 0x4D, 0x28, 0xC2, - 0x00, 0x00, 0x38, 0xAF, 0xC2, 0x1A, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, - 0x38, 0xAF, 0x25, 0x06, 0x30, 0xB3, 0x01, 0x11, 0x77, 0xAD, 0x25, 0x05, - 0x02, 0x44, 0x28, 0x25, 0x06, 0x20, 0xAF, 0x9E, 0x24, 0x87, 0x26, 0x03, - 0x01, 0x01, 0x00, 0x2E, 0x03, 0x02, 0xB2, 0x25, 0x02, 0x01, 0x15, 0x06, - 0x07, 0x2C, 0x06, 0x04, 0x01, 0x7F, 0x03, 0x00, 0x02, 0x02, 0x1F, 0x79, - 0x04, 0x5D, 0x79, 0x04, 0x4D, 0x79, 0x1A, 0x02, 0x00, 0x00, 0x00, 0xB3, - 0x01, 0x06, 0x78, 0xB1, 0x00, 0x00, 0xB8, 0x86, 0x06, 0x0E, 0x3B, 0x25, - 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00, 0xB8, 0x6D, 0x04, 0x08, - 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB9, 0x86, - 0x06, 0x0E, 0x3B, 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x00, 0x00, - 0xB9, 0x6D, 0x04, 0x08, 0x92, 0x06, 0x05, 0x24, 0x01, 0x00, 0x04, 0x00, - 0x00, 0x00, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x04, 0x00, 0x04, - 0x80, 0x55, 0x25, 0x01, 0x81, 0x40, 0x0D, 0x06, 0x07, 0x24, 0x01, 0x00, - 0x00, 0x04, 0x80, 0x47, 0x25, 0x01, 0x81, 0x60, 0x0D, 0x06, 0x0E, 0x01, - 0x1F, 0x15, 0x01, 0x01, 0xA3, 0x01, 0x81, 0x00, 0x01, 0x8F, 0x7F, 0x04, - 0x32, 0x25, 0x01, 0x81, 0x70, 0x0D, 0x06, 0x0F, 0x01, 0x0F, 0x15, 0x01, - 0x02, 0xA3, 0x01, 0x90, 0x00, 0x01, 0x83, 0xFF, 0x7F, 0x04, 0x1C, 0x25, - 0x01, 0x81, 0x78, 0x0D, 0x06, 0x11, 0x01, 0x07, 0x15, 0x01, 0x03, 0xA3, - 0x01, 0x84, 0x80, 0x00, 0x01, 0x80, 0xC3, 0xFF, 0x7F, 0x04, 0x04, 0x24, - 0x01, 0x00, 0x00, 0x72, 0x05, 0x03, 0x24, 0x01, 0x00, 0x00, 0x00, 0x3B, - 0x25, 0x05, 0x06, 0x42, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xBA, 0x34, 0x25, - 0x3D, 0x06, 0x03, 0x3B, 0x24, 0x00, 0x01, 0x06, 0x0E, 0x3B, 0x25, 0x01, - 0x06, 0x14, 0x01, 0x02, 0x10, 0x06, 0x04, 0x42, 0x01, 0x7F, 0x00, 0x01, - 0x3F, 0x15, 0x09, 0x00, 0x00, 0x25, 0x06, 0x06, 0x0B, 0xA2, 0x34, 0x41, - 0x04, 0x77, 0x24, 0x25, 0x00, 0x00, 0xB3, 0x01, 0x03, 0x78, 0xAD, 0xBA, - 0x06, 0x02, 0x55, 0x28, 0x00, 0x00, 0x3B, 0x25, 0x06, 0x07, 0x31, 0x25, - 0x06, 0x01, 0x19, 0x04, 0x76, 0x42, 0x00, 0x00, 0x01, 0x01, 0x78, 0xAC, - 0x01, 0x01, 0x10, 0x06, 0x02, 0x43, 0x28, 0xBA, 0x3E, 0x00, 0x04, 0xB3, - 0x25, 0x01, 0x17, 0x01, 0x18, 0x72, 0x05, 0x02, 0x48, 0x28, 0x01, 0x18, - 0x11, 0x03, 0x00, 0x75, 0xAD, 0xA8, 0x02, 0x00, 0x06, 0x0C, 0x01, 0x80, - 0x64, 0x08, 0x03, 0x01, 0xA8, 0x02, 0x01, 0x09, 0x04, 0x0E, 0x25, 0x01, - 0x32, 0x0D, 0x06, 0x04, 0x01, 0x80, 0x64, 0x09, 0x01, 0x8E, 0x6C, 0x09, - 0x03, 0x01, 0x02, 0x01, 0x01, 0x82, 0x6D, 0x08, 0x02, 0x01, 0x01, 0x03, - 0x09, 0x01, 0x04, 0x0C, 0x09, 0x02, 0x01, 0x01, 0x80, 0x63, 0x09, 0x01, - 0x80, 0x64, 0x0C, 0x0A, 0x02, 0x01, 0x01, 0x83, 0x0F, 0x09, 0x01, 0x83, - 0x10, 0x0C, 0x09, 0x03, 0x03, 0x01, 0x01, 0x01, 0x0C, 0xA9, 0x41, 0x01, - 0x01, 0x0E, 0x02, 0x01, 0x01, 0x04, 0x07, 0x3F, 0x02, 0x01, 0x01, 0x80, - 0x64, 0x07, 0x3E, 0x02, 0x01, 0x01, 0x83, 0x10, 0x07, 0x3F, 0x2F, 0x15, - 0x06, 0x03, 0x01, 0x18, 0x09, 0x94, 0x09, 0x7B, 0x25, 0x01, 0x05, 0x14, - 0x02, 0x03, 0x09, 0x03, 0x03, 0x01, 0x1F, 0x15, 0x01, 0x01, 0x3B, 0xA9, - 0x02, 0x03, 0x09, 0x41, 0x03, 0x03, 0x01, 0x00, 0x01, 0x17, 0xA9, 0x01, - 0x9C, 0x10, 0x08, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3B, 0xA9, 0x01, 0x3C, - 0x08, 0x02, 0x02, 0x09, 0x03, 0x02, 0x01, 0x00, 0x01, 0x3C, 0xA9, 0x02, - 0x02, 0x09, 0x03, 0x02, 0xBA, 0x25, 0x01, 0x2E, 0x11, 0x06, 0x0D, 0x24, - 0xBA, 0x25, 0x01, 0x30, 0x01, 0x39, 0x72, 0x06, 0x03, 0x24, 0x04, 0x74, - 0x01, 0x80, 0x5A, 0x10, 0x06, 0x02, 0x48, 0x28, 0x79, 0x02, 0x03, 0x02, - 0x02, 0x00, 0x01, 0xBA, 0x7D, 0x01, 0x0A, 0x08, 0x03, 0x00, 0xBA, 0x7D, - 0x02, 0x00, 0x09, 0x00, 0x02, 0x03, 0x00, 0x03, 0x01, 0xA8, 0x25, 0x02, - 0x01, 0x02, 0x00, 0x72, 0x05, 0x02, 0x48, 0x28, 0x00, 0x00, 0x34, 0xB3, - 0x01, 0x02, 0x78, 0x0B, 0xAB, 0x00, 0x03, 0x25, 0x03, 0x00, 0x03, 0x01, - 0x03, 0x02, 0xAD, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06, 0x02, 0x54, - 0x28, 0x25, 0x01, 0x00, 0x11, 0x06, 0x0B, 0x24, 0x25, 0x05, 0x04, 0x24, - 0x01, 0x00, 0x00, 0xBA, 0x04, 0x6F, 0x02, 0x01, 0x25, 0x05, 0x02, 0x50, - 0x28, 0x41, 0x03, 0x01, 0x02, 0x02, 0x37, 0x02, 0x02, 0x40, 0x03, 0x02, - 0x25, 0x06, 0x03, 0xBA, 0x04, 0x68, 0x24, 0x02, 0x00, 0x02, 0x01, 0x0A, - 0x00, 0x01, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x0D, 0x06, 0x01, 0x00, 0x01, - 0x81, 0x00, 0x0A, 0x25, 0x05, 0x02, 0x4E, 0x28, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x12, 0x06, 0x19, 0x02, 0x00, 0x41, 0x03, 0x00, - 0x25, 0x01, 0x83, 0xFF, 0xFF, 0x7F, 0x12, 0x06, 0x02, 0x4F, 0x28, 0x01, - 0x08, 0x0E, 0x3B, 0xBA, 0x34, 0x09, 0x04, 0x60, 0x00, 0x00, 0xAC, 0x95, - 0x00, 0x00, 0xAD, 0xC2, 0x00, 0x00, 0xB3, 0x76, 0xAD, 0x00, 0x01, 0xAD, - 0x25, 0x05, 0x02, 0x54, 0x28, 0xBA, 0x25, 0x01, 0x81, 0x00, 0x13, 0x06, - 0x02, 0x54, 0x28, 0x03, 0x00, 0x25, 0x06, 0x16, 0xBA, 0x02, 0x00, 0x25, - 0x01, 0x87, 0xFF, 0xFF, 0x7F, 0x13, 0x06, 0x02, 0x54, 0x28, 0x01, 0x08, - 0x0E, 0x09, 0x03, 0x00, 0x04, 0x67, 0x24, 0x02, 0x00, 0x00, 0x00, 0xAD, - 0x25, 0x01, 0x81, 0x7F, 0x12, 0x06, 0x08, 0xC2, 0x01, 0x00, 0x67, 0x37, - 0x01, 0x00, 0x00, 0x25, 0x67, 0x37, 0x67, 0x40, 0xA5, 0x01, 0x7F, 0x00, - 0x00, 0xB3, 0x01, 0x0C, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB6, 0x04, - 0x3E, 0x01, 0x12, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x33, - 0x01, 0x13, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x28, 0x01, - 0x14, 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x1D, 0x01, 0x16, - 0x30, 0x11, 0x06, 0x05, 0x24, 0x75, 0xB7, 0x04, 0x12, 0x01, 0x1E, 0x30, - 0x11, 0x06, 0x05, 0x24, 0x75, 0xB5, 0x04, 0x07, 0x42, 0xAE, 0x01, 0x00, - 0x01, 0x00, 0x24, 0x00, 0x01, 0xBA, 0x03, 0x00, 0x02, 0x00, 0x01, 0x05, - 0x14, 0x01, 0x01, 0x15, 0x2D, 0x02, 0x00, 0x01, 0x06, 0x14, 0x25, 0x01, - 0x01, 0x15, 0x06, 0x02, 0x46, 0x28, 0x01, 0x04, 0x0E, 0x02, 0x00, 0x01, - 0x1F, 0x15, 0x25, 0x01, 0x1F, 0x11, 0x06, 0x02, 0x47, 0x28, 0x09, 0x00, - 0x00, 0x25, 0x05, 0x05, 0x01, 0x00, 0x01, 0x7F, 0x00, 0xB3, 0x00, 0x01, - 0xAD, 0x25, 0x05, 0x05, 0x67, 0x37, 0x01, 0x7F, 0x00, 0x01, 0x01, 0x03, - 0x00, 0x9F, 0x25, 0x01, 0x83, 0xFF, 0x7E, 0x11, 0x06, 0x16, 0x24, 0x25, - 0x06, 0x10, 0xA0, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x84, 0x03, 0x00, 0x04, 0x6D, 0x04, 0x1B, 0x25, 0x05, 0x05, 0x24, - 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x25, 0x06, 0x0B, - 0x9F, 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x04, 0x6D, 0x24, - 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01, 0x7F, 0x00, - 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xA1, 0x25, 0x05, - 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, 0x00, 0x04, - 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, 0x37, 0x01, - 0x7F, 0x00, 0x01, 0xAD, 0x01, 0x01, 0x03, 0x00, 0x25, 0x06, 0x10, 0xBA, - 0x25, 0x05, 0x05, 0x24, 0xC2, 0x01, 0x00, 0x00, 0x02, 0x00, 0x84, 0x03, - 0x00, 0x04, 0x6D, 0x24, 0x02, 0x00, 0x25, 0x05, 0x01, 0x00, 0x41, 0x67, - 0x37, 0x01, 0x7F, 0x00, 0x00, 0xBA, 0x01, 0x08, 0x0E, 0x3B, 0xBA, 0x34, - 0x09, 0x00, 0x00, 0xBA, 0x3B, 0xBA, 0x01, 0x08, 0x0E, 0x34, 0x09, 0x00, - 0x00, 0x25, 0x05, 0x02, 0x4F, 0x28, 0x41, 0xBB, 0x00, 0x00, 0x32, 0x25, - 0x01, 0x00, 0x13, 0x06, 0x01, 0x00, 0x24, 0x19, 0x04, 0x74, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x0B, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, - 0x1F, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0xC3, - 0x24, 0x00, 0x00, 0x25, 0x06, 0x07, 0xC4, 0x25, 0x06, 0x01, 0x19, 0x04, - 0x76, 0x00, 0x00, 0x01, 0x00, 0x30, 0x31, 0x0B, 0x42, 0x00, 0x00, 0x01, - 0x81, 0x70, 0x00, 0x00, 0x01, 0x82, 0x0D, 0x00, 0x00, 0x01, 0x82, 0x22, - 0x00, 0x00, 0x01, 0x82, 0x05, 0x00, 0x00, 0x01, 0x03, 0x33, 0x01, 0x03, - 0x33, 0x00, 0x00, 0x25, 0x01, 0x83, 0xFB, 0x50, 0x01, 0x83, 0xFD, 0x5F, - 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x25, 0x01, 0x83, 0xB0, 0x00, - 0x01, 0x83, 0xBF, 0x7F, 0x72, 0x06, 0x04, 0x24, 0x01, 0x00, 0x00, 0x01, - 0x83, 0xFF, 0x7F, 0x15, 0x01, 0x83, 0xFF, 0x7E, 0x0D, 0x00 -}; - -static const uint16_t t0_caddr[] = { - 0, - 5, - 10, - 15, - 20, - 25, - 29, - 33, - 37, - 41, - 45, - 49, - 53, - 57, - 61, - 65, - 69, - 73, - 77, - 81, - 85, - 89, - 93, - 97, - 101, - 105, - 109, - 113, - 117, - 121, - 125, - 130, - 135, - 140, - 145, - 150, - 155, - 160, - 165, - 173, - 178, - 183, - 188, - 193, - 198, - 202, - 207, - 212, - 217, - 238, - 243, - 248, - 253, - 282, - 297, - 302, - 308, - 314, - 319, - 327, - 335, - 341, - 346, - 357, - 992, - 1007, - 1011, - 1016, - 1021, - 1026, - 1031, - 1036, - 1150, - 1155, - 1167, - 1172, - 1177, - 1182, - 1186, - 1191, - 1196, - 1201, - 1206, - 1216, - 1221, - 1226, - 1238, - 1253, - 1258, - 1272, - 1294, - 1305, - 1408, - 1455, - 1488, - 1579, - 1585, - 1648, - 1655, - 1683, - 1711, - 1816, - 1858, - 1871, - 1883, - 1897, - 1912, - 2132, - 2146, - 2163, - 2172, - 2239, - 2295, - 2299, - 2303, - 2308, - 2356, - 2382, - 2458, - 2502, - 2513, - 2598, - 2636, - 2674, - 2684, - 2694, - 2703, - 2716, - 2720, - 2724, - 2728, - 2732, - 2736, - 2740, - 2744, - 2756, - 2764, - 2769, - 2774, - 2779, - 2784, - 2792 -}; - -#define T0_INTERPRETED 61 - -#define T0_ENTER(ip, rp, slot) do { \ - const unsigned char *t0_newip; \ - uint32_t t0_lnum; \ - t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \ - t0_lnum = t0_parse7E_unsigned(&t0_newip); \ - (rp) += t0_lnum; \ - *((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \ - (ip) = t0_newip; \ - } while (0) - -#define T0_DEFENTRY(name, slot) \ -void \ -name(void *ctx) \ -{ \ - t0_context *t0ctx = ctx; \ - t0ctx->ip = &t0_codeblock[0]; \ - T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \ -} - -T0_DEFENTRY(br_x509_minimal_init_main, 147) - -#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++) - -void -br_x509_minimal_run(void *t0ctx) -{ - uint32_t *dp, *rp; - const unsigned char *ip; - -#define T0_LOCAL(x) (*(rp - 2 - (x))) -#define T0_POP() (*-- dp) -#define T0_POPi() (*(int32_t *)(-- dp)) -#define T0_PEEK(x) (*(dp - 1 - (x))) -#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x))) -#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0) -#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0) -#define T0_RPOP() (*-- rp) -#define T0_RPOPi() (*(int32_t *)(-- rp)) -#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0) -#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0) -#define T0_ROLL(x) do { \ - size_t t0len = (size_t)(x); \ - uint32_t t0tmp = *(dp - 1 - t0len); \ - memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_SWAP() do { \ - uint32_t t0tmp = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_ROT() do { \ - uint32_t t0tmp = *(dp - 3); \ - *(dp - 3) = *(dp - 2); \ - *(dp - 2) = *(dp - 1); \ - *(dp - 1) = t0tmp; \ -} while (0) -#define T0_NROT() do { \ - uint32_t t0tmp = *(dp - 1); \ - *(dp - 1) = *(dp - 2); \ - *(dp - 2) = *(dp - 3); \ - *(dp - 3) = t0tmp; \ -} while (0) -#define T0_PICK(x) do { \ - uint32_t t0depth = (x); \ - T0_PUSH(T0_PEEK(t0depth)); \ -} while (0) -#define T0_CO() do { \ - goto t0_exit; \ -} while (0) -#define T0_RET() goto t0_next - - dp = ((t0_context *)t0ctx)->dp; - rp = ((t0_context *)t0ctx)->rp; - ip = ((t0_context *)t0ctx)->ip; - goto t0_next; - for (;;) { - uint32_t t0x; - - t0_next: - t0x = T0_NEXT(&ip); - if (t0x < T0_INTERPRETED) { - switch (t0x) { - int32_t t0off; - - case 0: /* ret */ - t0x = T0_RPOP(); - rp -= (t0x >> 16); - t0x &= 0xFFFF; - if (t0x == 0) { - ip = NULL; - goto t0_exit; - } - ip = &t0_codeblock[t0x]; - break; - case 1: /* literal constant */ - T0_PUSHi(t0_parse7E_signed(&ip)); - break; - case 2: /* read local */ - T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip))); - break; - case 3: /* write local */ - T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP(); - break; - case 4: /* jump */ - t0off = t0_parse7E_signed(&ip); - ip += t0off; - break; - case 5: /* jump if */ - t0off = t0_parse7E_signed(&ip); - if (T0_POP()) { - ip += t0off; - } - break; - case 6: /* jump if not */ - t0off = t0_parse7E_signed(&ip); - if (!T0_POP()) { - ip += t0off; - } - break; - case 7: { - /* %25 */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSHi(a % b); - - } - break; - case 8: { - /* * */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a * b); - - } - break; - case 9: { - /* + */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a + b); - - } - break; - case 10: { - /* - */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a - b); - - } - break; - case 11: { - /* -rot */ - T0_NROT(); - } - break; - case 12: { - /* / */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSHi(a / b); - - } - break; - case 13: { - /* < */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a < b)); - - } - break; - case 14: { - /* << */ - - int c = (int)T0_POPi(); - uint32_t x = T0_POP(); - T0_PUSH(x << c); - - } - break; - case 15: { - /* <= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a <= b)); - - } - break; - case 16: { - /* <> */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a != b)); - - } - break; - case 17: { - /* = */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(-(uint32_t)(a == b)); - - } - break; - case 18: { - /* > */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a > b)); - - } - break; - case 19: { - /* >= */ - - int32_t b = T0_POPi(); - int32_t a = T0_POPi(); - T0_PUSH(-(uint32_t)(a >= b)); - - } - break; - case 20: { - /* >> */ - - int c = (int)T0_POPi(); - int32_t x = T0_POPi(); - T0_PUSHi(x >> c); - - } - break; - case 21: { - /* and */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a & b); - - } - break; - case 22: { - /* blobcopy */ - - size_t len = T0_POP(); - unsigned char *src = (unsigned char *)CTX + T0_POP(); - unsigned char *dst = (unsigned char *)CTX + T0_POP(); - memcpy(dst, src, len); - - } - break; - case 23: { - /* check-direct-trust */ - - size_t u; - - for (u = 0; u < CTX->trust_anchors_num; u ++) { - const br_x509_trust_anchor *ta; - unsigned char hashed_DN[64]; - int kt; - - ta = &CTX->trust_anchors[u]; - if (ta->flags & BR_X509_TA_CA) { - continue; - } - hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->current_dn_hash, DNHASH_LEN)) { - continue; - } - kt = CTX->pkey.key_type; - if ((ta->pkey.key_type & 0x0F) != kt) { - continue; - } - switch (kt) { - - case BR_KEYTYPE_RSA: - if (!eqbigint(CTX->pkey.key.rsa.n, - CTX->pkey.key.rsa.nlen, - ta->pkey.key.rsa.n, - ta->pkey.key.rsa.nlen) - || !eqbigint(CTX->pkey.key.rsa.e, - CTX->pkey.key.rsa.elen, - ta->pkey.key.rsa.e, - ta->pkey.key.rsa.elen)) - { - continue; - } - break; - - case BR_KEYTYPE_EC: - if (CTX->pkey.key.ec.curve != ta->pkey.key.ec.curve - || CTX->pkey.key.ec.qlen != ta->pkey.key.ec.qlen - || memcmp(CTX->pkey.key.ec.q, - ta->pkey.key.ec.q, - ta->pkey.key.ec.qlen) != 0) - { - continue; - } - break; - - default: - continue; - } - - /* - * Direct trust match! - */ - CTX->err = BR_ERR_X509_OK; - T0_CO(); - } - - } - break; - case 24: { - /* check-trust-anchor-CA */ - - size_t u; - - for (u = 0; u < CTX->trust_anchors_num; u ++) { - const br_x509_trust_anchor *ta; - unsigned char hashed_DN[64]; - - ta = &CTX->trust_anchors[u]; - if (!(ta->flags & BR_X509_TA_CA)) { - continue; - } - hash_dn(CTX, ta->dn.data, ta->dn.len, hashed_DN); - if (memcmp(hashed_DN, CTX->saved_dn_hash, DNHASH_LEN)) { - continue; - } - if (verify_signature(CTX, &ta->pkey) == 0) { - CTX->err = BR_ERR_X509_OK; - T0_CO(); - } - } - - } - break; - case 25: { - /* co */ - T0_CO(); - } - break; - case 26: { - /* compute-dn-hash */ - - CTX->dn_hash_impl->out(&CTX->dn_hash.vtable, CTX->current_dn_hash); - CTX->do_dn_hash = 0; - - } - break; - case 27: { - /* compute-tbs-hash */ - - int id = T0_POPi(); - size_t len; - len = br_multihash_out(&CTX->mhash, id, CTX->tbs_hash); - T0_PUSH(len); - - } - break; - case 28: { - /* copy-ee-ec-pkey */ - - size_t qlen = T0_POP(); - uint32_t curve = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, qlen); - CTX->pkey.key_type = BR_KEYTYPE_EC; - CTX->pkey.key.ec.curve = curve; - CTX->pkey.key.ec.q = CTX->ee_pkey_data; - CTX->pkey.key.ec.qlen = qlen; - - } - break; - case 29: { - /* copy-ee-rsa-pkey */ - - size_t elen = T0_POP(); - size_t nlen = T0_POP(); - memcpy(CTX->ee_pkey_data, CTX->pkey_data, nlen + elen); - CTX->pkey.key_type = BR_KEYTYPE_RSA; - CTX->pkey.key.rsa.n = CTX->ee_pkey_data; - CTX->pkey.key.rsa.nlen = nlen; - CTX->pkey.key.rsa.e = CTX->ee_pkey_data + nlen; - CTX->pkey.key.rsa.elen = elen; - - } - break; - case 30: { - /* copy-name-SAN */ - - unsigned tag = T0_POP(); - unsigned ok = T0_POP(); - size_t u, len; - - len = CTX->pad[0]; - for (u = 0; u < CTX->num_name_elts; u ++) { - br_name_element *ne; - - ne = &CTX->name_elts[u]; - if (ne->status == 0 && ne->oid[0] == 0 && ne->oid[1] == tag) { - if (ok && ne->len > len) { - memcpy(ne->buf, CTX->pad + 1, len); - ne->buf[len] = 0; - ne->status = 1; - } else { - ne->status = -1; - } - break; - } - } - - } - break; - case 31: { - /* copy-name-element */ - - size_t len; - int32_t off = T0_POPi(); - int ok = T0_POPi(); - - if (off >= 0) { - br_name_element *ne = &CTX->name_elts[off]; - - if (ok) { - len = CTX->pad[0]; - if (len < ne->len) { - memcpy(ne->buf, CTX->pad + 1, len); - ne->buf[len] = 0; - ne->status = 1; - } else { - ne->status = -1; - } - } else { - ne->status = -1; - } - } - - } - break; - case 32: { - /* data-get8 */ - - size_t addr = T0_POP(); - T0_PUSH(t0_datablock[addr]); - - } - break; - case 33: { - /* dn-hash-length */ - - T0_PUSH(DNHASH_LEN); - - } - break; - case 34: { - /* do-ecdsa-vrfy */ - - size_t qlen = T0_POP(); - int curve = T0_POP(); - br_x509_pkey pk; - - pk.key_type = BR_KEYTYPE_EC; - pk.key.ec.curve = curve; - pk.key.ec.q = CTX->pkey_data; - pk.key.ec.qlen = qlen; - T0_PUSH(verify_signature(CTX, &pk)); - - } - break; - case 35: { - /* do-rsa-vrfy */ - - size_t elen = T0_POP(); - size_t nlen = T0_POP(); - br_x509_pkey pk; - - pk.key_type = BR_KEYTYPE_RSA; - pk.key.rsa.n = CTX->pkey_data; - pk.key.rsa.nlen = nlen; - pk.key.rsa.e = CTX->pkey_data + nlen; - pk.key.rsa.elen = elen; - T0_PUSH(verify_signature(CTX, &pk)); - - } - break; - case 36: { - /* drop */ - (void)T0_POP(); - } - break; - case 37: { - /* dup */ - T0_PUSH(T0_PEEK(0)); - } - break; - case 38: { - /* eqOID */ - - const unsigned char *a2 = &t0_datablock[T0_POP()]; - const unsigned char *a1 = &CTX->pad[0]; - size_t len = a1[0]; - int x; - if (len == a2[0]) { - x = -(memcmp(a1 + 1, a2 + 1, len) == 0); - } else { - x = 0; - } - T0_PUSH((uint32_t)x); - - } - break; - case 39: { - /* eqblob */ - - size_t len = T0_POP(); - const unsigned char *a2 = (const unsigned char *)CTX + T0_POP(); - const unsigned char *a1 = (const unsigned char *)CTX + T0_POP(); - T0_PUSHi(-(memcmp(a1, a2, len) == 0)); - - } - break; - case 40: { - /* fail */ - - CTX->err = T0_POPi(); - T0_CO(); - - } - break; - case 41: { - /* get-system-date */ - - if (CTX->days == 0 && CTX->seconds == 0) { -#if BR_USE_UNIX_TIME - time_t x = time(NULL); - - T0_PUSH((uint32_t)(x / 86400) + 719528); - T0_PUSH((uint32_t)(x % 86400)); -#elif BR_USE_WIN32_TIME - FILETIME ft; - uint64_t x; - - GetSystemTimeAsFileTime(&ft); - x = ((uint64_t)ft.dwHighDateTime << 32) - + (uint64_t)ft.dwLowDateTime; - x = (x / 10000000); - T0_PUSH((uint32_t)(x / 86400) + 584754); - T0_PUSH((uint32_t)(x % 86400)); -#else - CTX->err = BR_ERR_X509_TIME_UNKNOWN; - T0_CO(); -#endif - } else { - T0_PUSH(CTX->days); - T0_PUSH(CTX->seconds); - } - - } - break; - case 42: { - /* get16 */ - - uint32_t addr = T0_POP(); - T0_PUSH(*(uint16_t *)(void *)((unsigned char *)CTX + addr)); - - } - break; - case 43: { - /* get32 */ - - uint32_t addr = T0_POP(); - T0_PUSH(*(uint32_t *)(void *)((unsigned char *)CTX + addr)); - - } - break; - case 44: { - /* match-server-name */ - - size_t n1, n2; - - if (CTX->server_name == NULL) { - T0_PUSH(0); - T0_RET(); - } - n1 = strlen(CTX->server_name); - n2 = CTX->pad[0]; - if (n1 == n2 && eqnocase(&CTX->pad[1], CTX->server_name, n1)) { - T0_PUSHi(-1); - T0_RET(); - } - if (n2 >= 2 && CTX->pad[1] == '*' && CTX->pad[2] == '.') { - size_t u; - - u = 0; - while (u < n1 && CTX->server_name[u] != '.') { - u ++; - } - u ++; - n1 -= u; - if ((n2 - 2) == n1 - && eqnocase(&CTX->pad[3], CTX->server_name + u, n1)) - { - T0_PUSHi(-1); - T0_RET(); - } - } - T0_PUSH(0); - - } - break; - case 45: { - /* neg */ - - uint32_t a = T0_POP(); - T0_PUSH(-a); - - } - break; - case 46: { - /* offset-name-element */ - - unsigned san = T0_POP(); - size_t u; - - for (u = 0; u < CTX->num_name_elts; u ++) { - if (CTX->name_elts[u].status == 0) { - const unsigned char *oid; - size_t len, off; - - oid = CTX->name_elts[u].oid; - if (san) { - if (oid[0] != 0 || oid[1] != 0) { - continue; - } - off = 2; - } else { - off = 0; - } - len = oid[off]; - if (len != 0 && len == CTX->pad[0] - && memcmp(oid + off + 1, - CTX->pad + 1, len) == 0) - { - T0_PUSH(u); - T0_RET(); - } - } - } - T0_PUSHi(-1); - - } - break; - case 47: { - /* or */ - - uint32_t b = T0_POP(); - uint32_t a = T0_POP(); - T0_PUSH(a | b); - - } - break; - case 48: { - /* over */ - T0_PUSH(T0_PEEK(1)); - } - break; - case 49: { - /* read-blob-inner */ - - uint32_t len = T0_POP(); - uint32_t addr = T0_POP(); - size_t clen = CTX->hlen; - if (clen > len) { - clen = (size_t)len; - } - if (addr != 0) { - memcpy((unsigned char *)CTX + addr, CTX->hbuf, clen); - } - if (CTX->do_mhash) { - br_multihash_update(&CTX->mhash, CTX->hbuf, clen); - } - if (CTX->do_dn_hash) { - CTX->dn_hash_impl->update( - &CTX->dn_hash.vtable, CTX->hbuf, clen); - } - CTX->hbuf += clen; - CTX->hlen -= clen; - T0_PUSH(addr + clen); - T0_PUSH(len - clen); - - } - break; - case 50: { - /* read8-low */ - - if (CTX->hlen == 0) { - T0_PUSHi(-1); - } else { - unsigned char x = *CTX->hbuf ++; - if (CTX->do_mhash) { - br_multihash_update(&CTX->mhash, &x, 1); - } - if (CTX->do_dn_hash) { - CTX->dn_hash_impl->update(&CTX->dn_hash.vtable, &x, 1); - } - CTX->hlen --; - T0_PUSH(x); - } - - } - break; - case 51: { - /* roll */ - T0_ROLL(T0_POP()); - } - break; - case 52: { - /* rot */ - T0_ROT(); - } - break; - case 53: { - /* set16 */ - - uint32_t addr = T0_POP(); - *(uint16_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); - - } - break; - case 54: { - /* set32 */ - - uint32_t addr = T0_POP(); - *(uint32_t *)(void *)((unsigned char *)CTX + addr) = T0_POP(); - - } - break; - case 55: { - /* set8 */ - - uint32_t addr = T0_POP(); - *((unsigned char *)CTX + addr) = (unsigned char)T0_POP(); - - } - break; - case 56: { - /* start-dn-hash */ - - CTX->dn_hash_impl->init(&CTX->dn_hash.vtable); - CTX->do_dn_hash = 1; - - } - break; - case 57: { - /* start-tbs-hash */ - - br_multihash_init(&CTX->mhash); - CTX->do_mhash = 1; - - } - break; - case 58: { - /* stop-tbs-hash */ - - CTX->do_mhash = 0; - - } - break; - case 59: { - /* swap */ - T0_SWAP(); - } - break; - case 60: { - /* zero-server-name */ - - T0_PUSHi(-(CTX->server_name == NULL)); - - } - break; - } - - } else { - T0_ENTER(ip, rp, t0x); - } - } -t0_exit: - ((t0_context *)t0ctx)->dp = dp; - ((t0_context *)t0ctx)->rp = rp; - ((t0_context *)t0ctx)->ip = ip; -} - - - -/* - * Verify the signature on the certificate with the provided public key. - * This function checks the public key type with regards to the expected - * type. Returned value is either 0 on success, or a non-zero error code. - */ -static int -verify_signature(br_x509_minimal_context *ctx, const br_x509_pkey *pk) -{ - int kt; - - kt = ctx->cert_signer_key_type; - if ((pk->key_type & 0x0F) != kt) { - return BR_ERR_X509_WRONG_KEY_TYPE; - } - switch (kt) { - unsigned char tmp[64]; - - case BR_KEYTYPE_RSA: - if (ctx->irsa == 0) { - return BR_ERR_X509_UNSUPPORTED; - } - if (!ctx->irsa(ctx->cert_sig, ctx->cert_sig_len, - &t0_datablock[ctx->cert_sig_hash_oid], - ctx->cert_sig_hash_len, &pk->key.rsa, tmp)) - { - return BR_ERR_X509_BAD_SIGNATURE; - } - if (memcmp(ctx->tbs_hash, tmp, ctx->cert_sig_hash_len) != 0) { - return BR_ERR_X509_BAD_SIGNATURE; - } - return 0; - - case BR_KEYTYPE_EC: - if (ctx->iecdsa == 0) { - return BR_ERR_X509_UNSUPPORTED; - } - if (!ctx->iecdsa(ctx->iec, ctx->tbs_hash, - ctx->cert_sig_hash_len, &pk->key.ec, - ctx->cert_sig, ctx->cert_sig_len)) - { - return BR_ERR_X509_BAD_SIGNATURE; - } - return 0; - - default: - return BR_ERR_X509_UNSUPPORTED; - } -} - - - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/bearssl/x509_minimal_full.c b/src/tls/bearssl/x509_minimal_full.c deleted file mode 100644 index c0dc6c7c7..000000000 --- a/src/tls/bearssl/x509_minimal_full.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "inner.h" - -/* see bearssl_x509.h */ -void -br_x509_minimal_init_full(br_x509_minimal_context *xc, - const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) -{ - /* - * All hash functions are activated. - * Note: the X.509 validation engine will nonetheless refuse to - * validate signatures that use MD5 as hash function. - */ - static const br_hash_class *hashes[] = { - &br_md5_vtable, - &br_sha1_vtable, - &br_sha224_vtable, - &br_sha256_vtable, - &br_sha384_vtable, - &br_sha512_vtable - }; - - int id; - - br_x509_minimal_init(xc, &br_sha256_vtable, - trust_anchors, trust_anchors_num); - br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy); - br_x509_minimal_set_ecdsa(xc, - &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1); - for (id = br_md5_ID; id <= br_sha512_ID; id ++) { - const br_hash_class *hc; - - hc = hashes[id - 1]; - br_x509_minimal_set_hash(xc, id, hc); - } -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/utility/eccX08_asn1.h b/src/tls/utility/eccX08_asn1.h deleted file mode 100644 index 571c56605..000000000 --- a/src/tls/utility/eccX08_asn1.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2018 Arduino SA. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _ECCX08_ASN1_H_ -#define _ECCX08_ASN1_H_ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "../bearssl/bearssl.h" - -size_t -eccX08_sign_asn1(const br_ec_impl *impl, - const br_hash_class *hf, const void *hash_value, - const br_ec_private_key *sk, void *sig); - -uint32_t -eccX08_vrfy_asn1(const br_ec_impl *impl, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len); - -#endif /* #ifdef BOARD_HAS_ECCX08 */ - -#endif diff --git a/src/tls/utility/eccX08_sign_asn1.cpp b/src/tls/utility/eccX08_sign_asn1.cpp deleted file mode 100644 index 95be607fe..000000000 --- a/src/tls/utility/eccX08_sign_asn1.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * Copyright (c) 2018 Arduino SA. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "eccX08_asn1.h" - -#include - -#define BR_MAX_EC_SIZE 528 -#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -size_t -eccX08_sign_asn1(const br_ec_impl * /*impl*/, - const br_hash_class * /*hf*/, const void *hash_value, - const br_ec_private_key *sk, void *sig) -{ - unsigned char rsig[(ORDER_LEN << 1) + 12]; - size_t sig_len; - - if (sk->curve != BR_EC_secp256r1) { - return 0; - } - - if (!ECCX08.ecSign((int)(sk->x), (const uint8_t*)hash_value, (uint8_t*)rsig)) { - return 0; - } - sig_len = 64; - - sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len); - memcpy(sig, rsig, sig_len); - return sig_len; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/utility/eccX08_vrfy_asn1.cpp b/src/tls/utility/eccX08_vrfy_asn1.cpp deleted file mode 100644 index 4745a6ec5..000000000 --- a/src/tls/utility/eccX08_vrfy_asn1.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016 Thomas Pornin - * Copyright (c) 2018 Arduino SA. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#ifdef BOARD_HAS_ECCX08 - -#include "eccX08_asn1.h" - -#include - -#define BR_MAX_EC_SIZE 528 -#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3) - -uint32_t -eccX08_vrfy_asn1(const br_ec_impl * /*impl*/, - const void *hash, size_t hash_len, - const br_ec_public_key *pk, - const void *sig, size_t sig_len) -{ - /* - * We use a double-sized buffer because a malformed ASN.1 signature - * may trigger a size expansion when converting to "raw" format. - */ - unsigned char rsig[(FIELD_LEN << 2) + 24]; - - if (sig_len > ((sizeof rsig) >> 1)) { - return 0; - } - - memcpy(rsig, sig, sig_len); - sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len); - - if (hash_len != 32 || pk->curve != BR_EC_secp256r1 || pk->qlen != 65 || sig_len != 64) { - return 0; - } - - // TODO: understand why the public key is &pk->q[1] instead of &pk->q[0] ... - if (!ECCX08.ecdsaVerify((const uint8_t*)hash, (const uint8_t*)rsig, (const uint8_t*)&pk->q[1])) { - return 0; - } - - return 1; -} - -#endif /* #ifdef BOARD_HAS_ECCX08 */ From c16a39c6d32d7552237378c0d3af133b1b67e8bf Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 9 Jan 2024 09:40:35 +0100 Subject: [PATCH 23/40] Add ArduinoBearSSL in compile example workflow --- .github/workflows/compile-examples.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index b465ffd85..5eb4f66d9 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -105,6 +105,7 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero @@ -122,6 +123,7 @@ jobs: - name: arduino:samd - name: arduino:mbed_nano libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero @@ -154,6 +156,7 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero @@ -170,6 +173,7 @@ jobs: # Install samd platform via Boards Manager - name: arduino:samd libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard - name: RTCZero @@ -186,6 +190,7 @@ jobs: # Install mbed_portenta platform via Boards Manager - name: arduino:mbed_portenta libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Arduino_Cellular - name: Blues Wireless Notecard @@ -214,6 +219,7 @@ jobs: # Install mbed_opta platform via Boards Manager - name: arduino:mbed_opta libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | @@ -228,6 +234,7 @@ jobs: # Install mbed_giga platform via Boards Manager - name: arduino:mbed_giga libraries: | + - name: ArduinoBearSSL - name: ArduinoECCX08 - name: Blues Wireless Notecard sketch-paths: | From 6222f1b0e67a4b46a7bcc40d86a3bd9458c1650d Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 Jan 2024 14:20:14 +0100 Subject: [PATCH 24/40] Adapt BearSSL client profile init to allow profile configuration from ArduinoIoTCloud to ArduinoBearSSL library - remove unnecessary include - rename - add include guards - move into tls folder --- .../aiotc_profile.c => BearSSLClientProfile.h} | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) rename src/tls/{profile/aiotc_profile.c => BearSSLClientProfile.h} (92%) diff --git a/src/tls/profile/aiotc_profile.c b/src/tls/BearSSLClientProfile.h similarity index 92% rename from src/tls/profile/aiotc_profile.c rename to src/tls/BearSSLClientProfile.h index e546b7577..696fc6509 100644 --- a/src/tls/profile/aiotc_profile.c +++ b/src/tls/BearSSLClientProfile.h @@ -22,11 +22,16 @@ * SOFTWARE. */ +#ifndef _BEAR_SSL_CLIENT_PROFILE_H_ +#define _BEAR_SSL_CLIENT_PROFILE_H_ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + #include #ifdef BOARD_HAS_ECCX08 -#include "../bearssl/inner.h" - /* see bearssl_ssl.h */ void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) { @@ -99,3 +104,6 @@ void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_contex } #endif /* #ifdef BOARD_HAS_ECCX08 */ + +#endif /* _BEAR_SSL_CLIENT_PROFILE_H_ */ + From 95e3cff95b2f48ef4407bde7fa826a199fa848af Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 4 Jan 2024 14:33:04 +0100 Subject: [PATCH 25/40] Add ArduinoBearSSLConfig.h file and include it in the build to allow library configuration --- src/ArduinoBearSSLConfig.h | 41 +++++++++++++++++++++++++++++++++ src/tls/utility/TLSClientMqtt.h | 3 ++- src/tls/utility/TLSClientOta.h | 3 ++- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/ArduinoBearSSLConfig.h diff --git a/src/ArduinoBearSSLConfig.h b/src/ArduinoBearSSLConfig.h new file mode 100644 index 000000000..621a5033d --- /dev/null +++ b/src/ArduinoBearSSLConfig.h @@ -0,0 +1,41 @@ +/* + This file is part of ArduinoIoTCloud. + + Copyright 2024 ARDUINO SA (http://www.arduino.cc/) + + This software is released under the GNU General Public License version 3, + which covers the main part of arduino-cli. + The terms of this license can be found at: + https://www.gnu.org/licenses/gpl-3.0.en.html + + You can be released from the requirements of the above licenses by purchasing + a commercial license. Buying such a license is mandatory if you want to modify or + otherwise use the software for commercial activities involving the Arduino + software without disclosing the source code of your own applications. To purchase + a commercial license, send an email to license@arduino.cc. +*/ + +#ifndef ARDUINO_BEARSSL_CONFIG_H_ +#define ARDUINO_BEARSSL_CONFIG_H_ + +/* Enabling this define allows the usage of ArduinoBearSSL without crypto chip. */ +//#define ARDUINO_DISABLE_ECCX08 + +/* Enable/Disable global instances*/ +#define ARDUINO_BEARSSL_DISABLE_AES128 +#define ARDUINO_BEARSSL_DISABLE_DES +#define ARDUINO_BEARSSL_DISABLE_MD5 +#define ARDUINO_BEARSSL_DISABLE_SHA1 +#define ARDUINO_BEARSSL_DISABLE_SHA256 + +#define ARDUINO_BEARSSL_DISABLE_KEY_DECODER + +/* If uncommented profile should be configured using client.setProfile(...) */ +#define ARDUINO_BEARSSL_DISABLE_FULL_CLIENT_PROFILE + +/* If uncommented TA should be configured via constructor */ +#define ARDUINO_BEARSSL_DISABLE_BUILTIN_TRUST_ANCHORS + +#define BEAR_SSL_CLIENT_CHAIN_SIZE 1 + +#endif /* ARDUINO_BEARSSL_CONFIG_H_ */ diff --git a/src/tls/utility/TLSClientMqtt.h b/src/tls/utility/TLSClientMqtt.h index a66ef430e..689eff2f8 100644 --- a/src/tls/utility/TLSClientMqtt.h +++ b/src/tls/utility/TLSClientMqtt.h @@ -35,7 +35,8 @@ enum class ArduinoIoTAuthenticationMode * Arduino Giga R1 * OPTA */ - #include + #include + #include class TLSClientMqtt : public BearSSLClient { #elif defined(ARDUINO_PORTENTA_C33) /* diff --git a/src/tls/utility/TLSClientOta.h b/src/tls/utility/TLSClientOta.h index d03c2d28c..6859a96e6 100644 --- a/src/tls/utility/TLSClientOta.h +++ b/src/tls/utility/TLSClientOta.h @@ -29,7 +29,8 @@ * Arduino Giga R1 * OPTA */ - #include + #include + #include class TLSClientOta : public BearSSLClient { #elif defined(ARDUINO_PORTENTA_C33) /* From 5ebefcdb6f2b11563c78b44ba2f80987ce409509 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 May 2024 16:30:57 +0200 Subject: [PATCH 26/40] Fix onGetTime --- src/tls/utility/TLSClientMqtt.cpp | 2 +- src/tls/utility/TLSClientOta.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls/utility/TLSClientMqtt.cpp b/src/tls/utility/TLSClientMqtt.cpp index c2fb95725..cd1824a71 100644 --- a/src/tls/utility/TLSClientMqtt.cpp +++ b/src/tls/utility/TLSClientMqtt.cpp @@ -46,7 +46,7 @@ void TLSClientMqtt::begin(ConnectionHandler & connection, ArduinoIoTAuthenticati setClient(connection.getClient()); setProfile(aiotc_client_profile_init); setTrustAnchors(ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM); - onGetTime(getTime); + ArduinoBearSSL.onGetTime(getTime); #elif defined(ARDUINO_PORTENTA_C33) (void)authMode; setClient(connection.getClient()); diff --git a/src/tls/utility/TLSClientOta.cpp b/src/tls/utility/TLSClientOta.cpp index 7f9ea981d..6e1b5e201 100644 --- a/src/tls/utility/TLSClientOta.cpp +++ b/src/tls/utility/TLSClientOta.cpp @@ -42,7 +42,7 @@ void TLSClientOta::begin(ConnectionHandler &connection) { setClient(*getNewClient(connection.getInterface())); setProfile(aiotc_client_profile_init); setTrustAnchors(ArduinoIoTCloudTrustAnchor, ArduinoIoTCloudTrustAnchor_NUM); - onGetTime(getTime); + ArduinoBearSSL.onGetTime(getTime); #elif defined(ARDUINO_PORTENTA_C33) setClient(*getNewClient(connection.getInterface())); setCACert(AIoTSSCert); From c7980fffba9c2748e72d5730f10dd5b112a31306 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 May 2024 16:34:26 +0200 Subject: [PATCH 27/40] Fix BearSSLClient profile configuration --- src/tls/BearSSLClientProfile.c | 106 ++++++++++++++++++++++++++++++ src/tls/BearSSLClientProfile.h | 71 +------------------- src/tls/utility/TLSClientMqtt.cpp | 5 +- src/tls/utility/TLSClientOta.cpp | 5 +- 4 files changed, 109 insertions(+), 78 deletions(-) create mode 100644 src/tls/BearSSLClientProfile.c diff --git a/src/tls/BearSSLClientProfile.c b/src/tls/BearSSLClientProfile.c new file mode 100644 index 000000000..cd787889f --- /dev/null +++ b/src/tls/BearSSLClientProfile.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/****************************************************************************** + * INCLUDE + ******************************************************************************/ + +#include +#ifdef BOARD_HAS_ECCX08 + +#include "bearssl/inner.h" + +/* see bearssl_ssl.h */ +void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) +{ + /* + * The "full" profile supports all implemented cipher suites. + * + * Rationale for suite order, from most important to least + * important rule: + * + * -- Don't use 3DES if AES or ChaCha20 is available. + * -- Try to have Forward Secrecy (ECDHE suite) if possible. + * -- When not using Forward Secrecy, ECDH key exchange is + * better than RSA key exchange (slightly more expensive on the + * client, but much cheaper on the server, and it implies smaller + * messages). + * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller code). + * -- GCM is better than CBC. + * -- AES-128 is preferred over AES-256 (AES-128 is already + * strong enough, and AES-256 is 40% more expensive). + */ + static const uint16_t suites[] = { + BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + }; + + /* + * Reset client context and set supported versions from TLS-1.0 + * to TLS-1.2 (inclusive). + */ + br_ssl_client_zero(cc); + br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); + + /* + * X.509 engine uses SHA-256 to hash certificate DN (for + * comparisons). + */ + br_x509_minimal_init(xc, &br_sha256_vtable, trust_anchors, trust_anchors_num); + + /* + * Set suites and asymmetric crypto implementations. We use the + * "i31" code for RSA (it is somewhat faster than the "i32" + * implementation). + * TODO: change that when better implementations are made available. + */ + br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0])); + br_ssl_engine_set_default_ecdsa(&cc->eng); + br_x509_minimal_set_ecdsa(xc, br_ssl_engine_get_ec(&cc->eng), br_ssl_engine_get_ecdsa(&cc->eng)); + + /* + * Set supported hash functions, for the SSL engine and for the + * X.509 engine. + */ + br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); + br_x509_minimal_set_hash(xc, br_sha256_ID, &br_sha256_vtable); + + /* + * Link the X.509 engine in the SSL engine. + */ + br_ssl_engine_set_x509(&cc->eng, &xc->vtable); + + /* + * Set the PRF implementations. + */ + br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); + + /* + * Symmetric encryption. We use the "default" implementations + * (fastest among constant-time implementations). + */ + br_ssl_engine_set_default_aes_gcm(&cc->eng); +} + +#endif /* #ifdef BOARD_HAS_ECCX08 */ + diff --git a/src/tls/BearSSLClientProfile.h b/src/tls/BearSSLClientProfile.h index 696fc6509..dbf9792db 100644 --- a/src/tls/BearSSLClientProfile.h +++ b/src/tls/BearSSLClientProfile.h @@ -32,76 +32,7 @@ #include #ifdef BOARD_HAS_ECCX08 -/* see bearssl_ssl.h */ -void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num) -{ - /* - * The "full" profile supports all implemented cipher suites. - * - * Rationale for suite order, from most important to least - * important rule: - * - * -- Don't use 3DES if AES or ChaCha20 is available. - * -- Try to have Forward Secrecy (ECDHE suite) if possible. - * -- When not using Forward Secrecy, ECDH key exchange is - * better than RSA key exchange (slightly more expensive on the - * client, but much cheaper on the server, and it implies smaller - * messages). - * -- ChaCha20+Poly1305 is better than AES/GCM (faster, smaller code). - * -- GCM is better than CBC. - * -- AES-128 is preferred over AES-256 (AES-128 is already - * strong enough, and AES-256 is 40% more expensive). - */ - static const uint16_t suites[] = { - BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - }; - - /* - * Reset client context and set supported versions from TLS-1.0 - * to TLS-1.2 (inclusive). - */ - br_ssl_client_zero(cc); - br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12); - - /* - * X.509 engine uses SHA-256 to hash certificate DN (for - * comparisons). - */ - br_x509_minimal_init(xc, &br_sha256_vtable, trust_anchors, trust_anchors_num); - - /* - * Set suites and asymmetric crypto implementations. We use the - * "i31" code for RSA (it is somewhat faster than the "i32" - * implementation). - * TODO: change that when better implementations are made available. - */ - br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0])); - br_ssl_engine_set_default_ecdsa(&cc->eng); - br_x509_minimal_set_ecdsa(xc, br_ssl_engine_get_ec(&cc->eng), br_ssl_engine_get_ecdsa(&cc->eng)); - - /* - * Set supported hash functions, for the SSL engine and for the - * X.509 engine. - */ - br_ssl_engine_set_hash(&cc->eng, br_sha256_ID, &br_sha256_vtable); - br_x509_minimal_set_hash(xc, br_sha256_ID, &br_sha256_vtable); - - /* - * Link the X.509 engine in the SSL engine. - */ - br_ssl_engine_set_x509(&cc->eng, &xc->vtable); - - /* - * Set the PRF implementations. - */ - br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf); - - /* - * Symmetric encryption. We use the "default" implementations - * (fastest among constant-time implementations). - */ - br_ssl_engine_set_default_aes_gcm(&cc->eng); -} +extern "C" void aiotc_client_profile_init(br_ssl_client_context *cc, br_x509_minimal_context *xc, const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); #endif /* #ifdef BOARD_HAS_ECCX08 */ diff --git a/src/tls/utility/TLSClientMqtt.cpp b/src/tls/utility/TLSClientMqtt.cpp index cd1824a71..d775f868d 100644 --- a/src/tls/utility/TLSClientMqtt.cpp +++ b/src/tls/utility/TLSClientMqtt.cpp @@ -24,11 +24,8 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" + #include "tls/BearSSLClientProfile.h" extern "C" { - void aiotc_client_profile_init(br_ssl_client_context *cc, - br_x509_minimal_context *xc, - const br_x509_trust_anchor *trust_anchors, - size_t trust_anchors_num); unsigned long getTime(); } #endif diff --git a/src/tls/utility/TLSClientOta.cpp b/src/tls/utility/TLSClientOta.cpp index 6e1b5e201..8d90e64b6 100644 --- a/src/tls/utility/TLSClientOta.cpp +++ b/src/tls/utility/TLSClientOta.cpp @@ -24,11 +24,8 @@ #ifdef BOARD_HAS_ECCX08 #include "tls/BearSSLTrustAnchors.h" + #include "tls/BearSSLClientProfile.h" extern "C" { - void aiotc_client_profile_init(br_ssl_client_context *cc, - br_x509_minimal_context *xc, - const br_x509_trust_anchor *trust_anchors, - size_t trust_anchors_num); unsigned long getTime(); } #endif From 6188ed59d9cc21f8a24c2b949f22abf309498de3 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Apr 2024 21:39:52 +0200 Subject: [PATCH 28/40] Enable builtin trust anchors and full profile to allow AWS connection --- src/ArduinoBearSSLConfig.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ArduinoBearSSLConfig.h b/src/ArduinoBearSSLConfig.h index 621a5033d..847cc3c3c 100644 --- a/src/ArduinoBearSSLConfig.h +++ b/src/ArduinoBearSSLConfig.h @@ -31,10 +31,10 @@ #define ARDUINO_BEARSSL_DISABLE_KEY_DECODER /* If uncommented profile should be configured using client.setProfile(...) */ -#define ARDUINO_BEARSSL_DISABLE_FULL_CLIENT_PROFILE +//#define ARDUINO_BEARSSL_DISABLE_FULL_CLIENT_PROFILE /* If uncommented TA should be configured via constructor */ -#define ARDUINO_BEARSSL_DISABLE_BUILTIN_TRUST_ANCHORS +//#define ARDUINO_BEARSSL_DISABLE_BUILTIN_TRUST_ANCHORS #define BEAR_SSL_CLIENT_CHAIN_SIZE 1 From 97f42eb4bb83168199f0d68e4c82ae5daf73550c Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 15 Apr 2024 21:49:46 +0200 Subject: [PATCH 29/40] Add example to connecto to ArduinoIoTCloud and AWS --- .../ArduinoIoTCloud-AWS-Basic.ino | 139 ++++++++++++++++++ .../arduino_secrets.h | 25 ++++ .../ArduinoIoTCloud-AWS-Basic/aws_config.h | 10 ++ .../thingProperties.h | 45 ++++++ 4 files changed, 219 insertions(+) create mode 100644 examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino create mode 100644 examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h create mode 100644 examples/ArduinoIoTCloud-AWS-Basic/aws_config.h create mode 100644 examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino new file mode 100644 index 000000000..50c55b9f1 --- /dev/null +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -0,0 +1,139 @@ +/* + This sketch demonstrates how to exchange data between your board and the Arduino IoT Cloud. + + * Connect a potentiometer (or other analog sensor) to A0. + * When the potentiometer (or sensor) value changes the data is sent to the Cloud. + * When you flip the switch in the Cloud dashboard the onboard LED lights gets turned ON or OFF. + + IMPORTANT: + This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. + On a LoRa board, if it is configured as a class A device (default and preferred option), + values from Cloud dashboard are received only after a value is sent to Cloud. + + The full list of compatible boards can be found here: + - https://github.com/arduino-libraries/ArduinoIoTCloud#what +*/ + +#include "thingProperties.h" + +unsigned long publishMillis = 0; +unsigned long connectMillis = 0; + +void setup() { + /* Initialize serial and wait up to 5 seconds for port to open */ + Serial.begin(9600); + while(!Serial); + + /* Configure LED pin as an output */ + pinMode(LED_BUILTIN, OUTPUT); + + /* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */ + initProperties(); + + /* Initialize Arduino IoT Cloud library */ + ArduinoCloud.begin(ArduinoIoTPreferredConnection, true, "iot.arduino.cc"); + + setDebugMessageLevel(5); + ArduinoCloud.printDebugInfo(); + + /* Initialize AWS Client */ + ArduinoBearSSL.onGetTime(getTime); + sslClientAWS.setEccSlot(AWS_SLOT, AWS_CERTIFICATE); + + mqttClientAWS.setId("ArduinoAWSClient"); + mqttClientAWS.onMessage(onMessageReceived); + mqttClientAWS.setConnectionTimeout(10 * 1000); + mqttClientAWS.setKeepAliveInterval(30 * 1000); + mqttClientAWS.setCleanSession(false); +} + +void loop() { + ArduinoCloud.update(); + potentiometer = analogRead(A0); + seconds = millis() / 1000; + + if (!ArduinoCloud.connected()) { + return; + } + + if (AWSIoTPreferredConnection.check() != NetworkConnectionState::CONNECTED) { + return; + } + + if (!mqttClientAWS.connected()) { + if (millis() - connectMillis > 5000) { + connectMillis = millis(); + // MQTT client is disconnected, connect + if (!connectMQTT()) { + return; + } + } else { + return; + } + } + + // poll for new MQTT messages and send keep alive + mqttClientAWS.poll(); + + // publish a message roughly every 5 seconds. + if (millis() - publishMillis > 5000) { + publishMillis = millis(); + + publishMessage(); + } +} + +/* + * 'onLedChange' is called when the "led" property of your Thing changes + */ +void onLedChange() { + Serial.print("LED set to "); + Serial.println(led); + digitalWrite(LED_BUILTIN, led); +} + +void onMessageReceived(int messageSize) +{ + // we received a message, print out the topic and contents + Serial.print("Received a message with topic '"); + Serial.print(mqttClientAWS.messageTopic()); + Serial.print("', length "); + Serial.print(messageSize); + Serial.println(" bytes:"); + + for (int i = 0; i < messageSize; i++) { + const char c = mqttClientAWS.read(); + Serial.print(c); + } + Serial.println(); +} + +int connectMQTT() { + Serial.print("Attempting to connect to MQTT broker: "); + Serial.print(AWS_BROKER); + Serial.println(" "); + + if (!mqttClientAWS.connect(AWS_BROKER, 8883)) { + // failed, retry + Serial.print("."); + return 0; + } + Serial.println(); + + Serial.println("You're connected to the MQTT broker"); + Serial.println(); + + // subscribe to a topic + mqttClientAWS.subscribe("arduino/incoming"); + return 1; +} + +void publishMessage() { + Serial.println("Publishing message"); + + // send message, the Print interface can be used to set the message contents + mqttClientAWS.beginMessage("arduino/outgoing"); + mqttClientAWS.print("hello "); + mqttClientAWS.print(millis()); + mqttClientAWS.endMessage(); +} diff --git a/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h new file mode 100644 index 000000000..2f69876fd --- /dev/null +++ b/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h @@ -0,0 +1,25 @@ +#include + +/* A complete list of supported boards with WiFi is available here: + * https://github.com/arduino-libraries/ArduinoIoTCloud/#what + */ +#if defined(BOARD_HAS_WIFI) && defined(USE_WIFI_CONNECTION) + #define SECRET_WIFI_SSID "" + #define SECRET_WIFI_PASS "" +#endif + +/* Portenta H7 + Ethernet shield */ +#if defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_MANUAL_CONNECTION) + #define SECRET_ETH_OPTIONAL_IP "" + #define SECRET_ETH_OPTIONAL_DNS "" + #define SECRET_ETH_OPTIONAL_GATEWAY "" + #define SECRET_ETH_OPTIONAL_NETMASK "" +#endif + +/* Portenta CAT.M1/NB IoT GNSS Shield */ +#if defined(BOARD_HAS_CATM1_NBIOT) && defined(USE_CATM1_NBIOT_CONNECTION) + #define SECRET_CATM_PIN "" + #define SECRET_CATM_APN "" + #define SECRET_CATM_LOGIN "" + #define SECRET_CATM_PASS "" +#endif diff --git a/examples/ArduinoIoTCloud-AWS-Basic/aws_config.h b/examples/ArduinoIoTCloud-AWS-Basic/aws_config.h new file mode 100644 index 000000000..07131d1da --- /dev/null +++ b/examples/ArduinoIoTCloud-AWS-Basic/aws_config.h @@ -0,0 +1,10 @@ +/* Fill in the hostname of your AWS IoT broker */ +#define AWS_BROKER "" + +#define AWS_SLOT 4 + +/* Fill in the boards public certificate */ +const char AWS_CERTIFICATE[] = R"( +-----BEGIN CERTIFICATE----- +-----END CERTIFICATE----- +)"; diff --git a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h new file mode 100644 index 000000000..d03dd120b --- /dev/null +++ b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h @@ -0,0 +1,45 @@ +#include +#include +#include "aws_config.h" + +#if !(defined(BOARD_STM32H7)) + #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" +#endif + +void onLedChange(); + +bool led; +int potentiometer; +int seconds; + +void initProperties() { + ArduinoCloud.addProperty(led, Permission::Write).onUpdate(onLedChange); + ArduinoCloud.addProperty(potentiometer, Permission::Read).publishOnChange(10); + ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); +} + +//#define USE_ETHERNET_DHCP_CONNECTION +//#define USE_ETHERNET_MANUAL_CONNECTION +#define USE_WIFI_CONNECTION +//#define USE_CATM1_NBIOT_CONNECTION + +#include "arduino_secrets.h" + +#if defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_CONNECTION) + /* DHCP mode */ + EthernetConnectionHandler ArduinoIoTPreferredConnection; + EthernetConnectionHandler AWSIoTPreferredConnection; +#elif defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_MANUAL_CONNECTION) + /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ + EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_ETH_OPTIONAL_IP, SECRET_ETH_OPTIONAL_DNS, SECRET_ETH_OPTIONAL_GATEWAY, SECRET_ETH_OPTIONAL_NETMASK); + EthernetConnectionHandler AWSIoTPreferredConnection(SECRET_ETH_OPTIONAL_IP, SECRET_ETH_OPTIONAL_DNS, SECRET_ETH_OPTIONAL_GATEWAY, SECRET_ETH_OPTIONAL_NETMASK); +#elif defined(BOARD_HAS_WIFI) && defined(USE_WIFI_CONNECTION) + WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); + WiFiConnectionHandler AWSIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); +#elif defined(BOARD_HAS_CATM1_NBIOT) && defined(USE_CATM1_NBIOT_CONNECTION) + CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_CATM_PIN, SECRET_CATM_APN, SECRET_CATM_LOGIN, SECRET_CATM_PASS); + CatM1ConnectionHandler AWSIoTPreferredConnection(SECRET_CATM_PIN, SECRET_CATM_APN, SECRET_CATM_LOGIN, SECRET_CATM_PASS); +#endif + +BearSSLClient sslClientAWS(AWSIoTPreferredConnection.getClient()); +MqttClient mqttClientAWS(sslClientAWS); From 6b4dda9527bb37d90fbdbd589eb5dd8e207bf9af Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 22 Apr 2024 16:20:30 +0200 Subject: [PATCH 30/40] Remove serial lock from AWS example --- examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index 50c55b9f1..16b97d292 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -22,7 +22,6 @@ unsigned long connectMillis = 0; void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); - while(!Serial); /* Configure LED pin as an output */ pinMode(LED_BUILTIN, OUTPUT); From 9340617b45d44bd441df9c55420aaa32e512e690 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 May 2024 17:54:11 +0200 Subject: [PATCH 31/40] Improve example --- .../ArduinoIoTCloud-AWS-Basic.ino | 33 +++++++++++++++-- .../arduino_secrets.h | 27 ++------------ .../{aws_config.h => aws_secrets.h} | 0 .../thingProperties.h | 36 ++++--------------- 4 files changed, 39 insertions(+), 57 deletions(-) rename examples/ArduinoIoTCloud-AWS-Basic/{aws_config.h => aws_secrets.h} (100%) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index 16b97d292..986f5cd92 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -15,10 +15,37 @@ */ #include "thingProperties.h" +#include "aws_secrets.h" + +Client& getDefaultClient() { + switch(ArduinoIoTPreferredConnection.getInterface()) { + +#ifdef BOARD_HAS_WIFI + case NetworkAdapter::WIFI: + static WiFiClient client; + return client; +#endif + +#ifdef BOARD_HAS_ETHERNET + case NetworkAdapter::ETHERNET: + static EthernetClient client; + return client; +#endif + + default: + Serial.println("Error: could not create default AWS client"); + break; + } + + +} unsigned long publishMillis = 0; unsigned long connectMillis = 0; +BearSSLClient sslClientAWS(getDefaultClient()); +MqttClient mqttClientAWS(sslClientAWS); + void setup() { /* Initialize serial and wait up to 5 seconds for port to open */ Serial.begin(9600); @@ -55,9 +82,9 @@ void loop() { return; } - if (AWSIoTPreferredConnection.check() != NetworkConnectionState::CONNECTED) { - return; - } + //if (AWSIoTPreferredConnection.check() != NetworkConnectionState::CONNECTED) { + // return; + //} if (!mqttClientAWS.connected()) { if (millis() - connectMillis > 5000) { diff --git a/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h b/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h index 2f69876fd..dee3e7210 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h +++ b/examples/ArduinoIoTCloud-AWS-Basic/arduino_secrets.h @@ -1,25 +1,2 @@ -#include - -/* A complete list of supported boards with WiFi is available here: - * https://github.com/arduino-libraries/ArduinoIoTCloud/#what - */ -#if defined(BOARD_HAS_WIFI) && defined(USE_WIFI_CONNECTION) - #define SECRET_WIFI_SSID "" - #define SECRET_WIFI_PASS "" -#endif - -/* Portenta H7 + Ethernet shield */ -#if defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_MANUAL_CONNECTION) - #define SECRET_ETH_OPTIONAL_IP "" - #define SECRET_ETH_OPTIONAL_DNS "" - #define SECRET_ETH_OPTIONAL_GATEWAY "" - #define SECRET_ETH_OPTIONAL_NETMASK "" -#endif - -/* Portenta CAT.M1/NB IoT GNSS Shield */ -#if defined(BOARD_HAS_CATM1_NBIOT) && defined(USE_CATM1_NBIOT_CONNECTION) - #define SECRET_CATM_PIN "" - #define SECRET_CATM_APN "" - #define SECRET_CATM_LOGIN "" - #define SECRET_CATM_PASS "" -#endif +#define SECRET_SSID "" +#define SECRET_OPTIONAL_PASS "" diff --git a/examples/ArduinoIoTCloud-AWS-Basic/aws_config.h b/examples/ArduinoIoTCloud-AWS-Basic/aws_secrets.h similarity index 100% rename from examples/ArduinoIoTCloud-AWS-Basic/aws_config.h rename to examples/ArduinoIoTCloud-AWS-Basic/aws_secrets.h diff --git a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h index d03dd120b..1c5ba8d71 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h @@ -1,10 +1,11 @@ +// Code generated by Arduino IoT Cloud, DO NOT EDIT. + #include #include -#include "aws_config.h" +#include "arduino_secrets.h" -#if !(defined(BOARD_STM32H7)) - #error "Please check Arduino IoT Cloud supported boards list: https://github.com/arduino-libraries/ArduinoIoTCloud/#what" -#endif +const char SSID[] = SECRET_SSID; // Network SSID (name) +const char PASS[] = SECRET_OPTIONAL_PASS; // Network password (use for WPA, or use as key for WEP) void onLedChange(); @@ -18,28 +19,5 @@ void initProperties() { ArduinoCloud.addProperty(seconds, Permission::Read).publishOnChange(1); } -//#define USE_ETHERNET_DHCP_CONNECTION -//#define USE_ETHERNET_MANUAL_CONNECTION -#define USE_WIFI_CONNECTION -//#define USE_CATM1_NBIOT_CONNECTION - -#include "arduino_secrets.h" - -#if defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_CONNECTION) - /* DHCP mode */ - EthernetConnectionHandler ArduinoIoTPreferredConnection; - EthernetConnectionHandler AWSIoTPreferredConnection; -#elif defined(BOARD_HAS_ETHERNET) && defined(USE_ETHERNET_MANUAL_CONNECTION) - /* Manual mode. It will fallback in DHCP mode if SECRET_OPTIONAL_IP is invalid or equal to "0.0.0.0" */ - EthernetConnectionHandler ArduinoIoTPreferredConnection(SECRET_ETH_OPTIONAL_IP, SECRET_ETH_OPTIONAL_DNS, SECRET_ETH_OPTIONAL_GATEWAY, SECRET_ETH_OPTIONAL_NETMASK); - EthernetConnectionHandler AWSIoTPreferredConnection(SECRET_ETH_OPTIONAL_IP, SECRET_ETH_OPTIONAL_DNS, SECRET_ETH_OPTIONAL_GATEWAY, SECRET_ETH_OPTIONAL_NETMASK); -#elif defined(BOARD_HAS_WIFI) && defined(USE_WIFI_CONNECTION) - WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); - WiFiConnectionHandler AWSIoTPreferredConnection(SECRET_WIFI_SSID, SECRET_WIFI_PASS); -#elif defined(BOARD_HAS_CATM1_NBIOT) && defined(USE_CATM1_NBIOT_CONNECTION) - CatM1ConnectionHandler ArduinoIoTPreferredConnection(SECRET_CATM_PIN, SECRET_CATM_APN, SECRET_CATM_LOGIN, SECRET_CATM_PASS); - CatM1ConnectionHandler AWSIoTPreferredConnection(SECRET_CATM_PIN, SECRET_CATM_APN, SECRET_CATM_LOGIN, SECRET_CATM_PASS); -#endif - -BearSSLClient sslClientAWS(AWSIoTPreferredConnection.getClient()); -MqttClient mqttClientAWS(sslClientAWS); +WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_OPTIONAL_PASS); + From 8e2e915c2aa4ba05bb8813ee2dd41cdef907c136 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 21 May 2024 17:57:52 +0200 Subject: [PATCH 32/40] Remove commented code --- .../ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index 986f5cd92..f77fab765 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -82,10 +82,6 @@ void loop() { return; } - //if (AWSIoTPreferredConnection.check() != NetworkConnectionState::CONNECTED) { - // return; - //} - if (!mqttClientAWS.connected()) { if (millis() - connectMillis > 5000) { connectMillis = millis(); From 243681a5af0707c196d53f302d39331f1fc62f2d Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 22 May 2024 10:15:53 +0200 Subject: [PATCH 33/40] Include arduino_secrets.h in the ino like we do cloudside --- examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino | 1 + examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index f77fab765..bbe968831 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -1,3 +1,4 @@ +#include "arduino_secrets.h" /* This sketch demonstrates how to exchange data between your board and the Arduino IoT Cloud. diff --git a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h index 1c5ba8d71..a49188449 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h @@ -2,7 +2,6 @@ #include #include -#include "arduino_secrets.h" const char SSID[] = SECRET_SSID; // Network SSID (name) const char PASS[] = SECRET_OPTIONAL_PASS; // Network password (use for WPA, or use as key for WEP) From 9734bb1ff08116a03b13d8814ad913ba1b6f9777 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 22 May 2024 10:16:25 +0200 Subject: [PATCH 34/40] Fix example header and cosmetics --- .../ArduinoIoTCloud-AWS-Basic.ino | 15 ++------------- .../ArduinoIoTCloud-AWS-Basic/thingProperties.h | 1 - 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index bbe968831..d713cfcae 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -1,15 +1,6 @@ #include "arduino_secrets.h" /* - This sketch demonstrates how to exchange data between your board and the Arduino IoT Cloud. - - * Connect a potentiometer (or other analog sensor) to A0. - * When the potentiometer (or sensor) value changes the data is sent to the Cloud. - * When you flip the switch in the Cloud dashboard the onboard LED lights gets turned ON or OFF. - - IMPORTANT: - This sketch works with WiFi, GSM, NB, Ethernet and Lora enabled boards supported by Arduino IoT Cloud. - On a LoRa board, if it is configured as a class A device (default and preferred option), - values from Cloud dashboard are received only after a value is sent to Cloud. + This sketch demonstrates how to connect to ArduinoIoTCloud and AWS IoT core. The full list of compatible boards can be found here: - https://github.com/arduino-libraries/ArduinoIoTCloud#what @@ -20,7 +11,7 @@ Client& getDefaultClient() { switch(ArduinoIoTPreferredConnection.getInterface()) { - + #ifdef BOARD_HAS_WIFI case NetworkAdapter::WIFI: static WiFiClient client; @@ -37,8 +28,6 @@ Client& getDefaultClient() { Serial.println("Error: could not create default AWS client"); break; } - - } unsigned long publishMillis = 0; diff --git a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h index a49188449..6717ea377 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h +++ b/examples/ArduinoIoTCloud-AWS-Basic/thingProperties.h @@ -19,4 +19,3 @@ void initProperties() { } WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_OPTIONAL_PASS); - From a93867d05cb1209ed31cf45f5005c493b26972e6 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 22 May 2024 10:17:21 +0200 Subject: [PATCH 35/40] Fix build using different names for aws clients --- .../ArduinoIoTCloud-AWS-Basic.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino index d713cfcae..3213a3bf8 100644 --- a/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino +++ b/examples/ArduinoIoTCloud-AWS-Basic/ArduinoIoTCloud-AWS-Basic.ino @@ -14,14 +14,14 @@ Client& getDefaultClient() { #ifdef BOARD_HAS_WIFI case NetworkAdapter::WIFI: - static WiFiClient client; - return client; + static WiFiClient wclient; + return wclient; #endif #ifdef BOARD_HAS_ETHERNET case NetworkAdapter::ETHERNET: - static EthernetClient client; - return client; + static EthernetClient eclient; + return eclient; #endif default: From f0be6b2328b365074893679b3bf4d6cb9e54cf0a Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 4 Apr 2025 16:40:24 +0200 Subject: [PATCH 36/40] Move BEAR_SSL_CLIENT_IBUF_SIZE inside ArduinoBearSSLConfig.h --- src/AIoTC_Config.h | 5 ----- src/ArduinoBearSSLConfig.h | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 779a4607f..4061cdd05 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -122,10 +122,6 @@ #define HAS_TCP #endif -#if defined(ARDUINO_NANO_RP2040_CONNECT) - #define BEAR_SSL_CLIENT_IBUF_SIZE (16384 + 325) // Allows download from storage API -#endif - #if defined(ARDUINO_EDGE_CONTROL) #define BOARD_HAS_SECRET_KEY #define HAS_TCP @@ -149,7 +145,6 @@ #endif // HAS_NOTECARD #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA) - #define BEAR_SSL_CLIENT_IBUF_SIZE (16384 + 325) // Allows download from storage API #define BOARD_STM32H7 #endif diff --git a/src/ArduinoBearSSLConfig.h b/src/ArduinoBearSSLConfig.h index 847cc3c3c..2c8d4ea99 100644 --- a/src/ArduinoBearSSLConfig.h +++ b/src/ArduinoBearSSLConfig.h @@ -38,4 +38,10 @@ #define BEAR_SSL_CLIENT_CHAIN_SIZE 1 +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) ||\ + defined(ARDUINO_GIGA) || defined(ARDUINO_NANO_RP2040_CONNECT) + /* Allows download from OTA storage API */ + #define BEAR_SSL_CLIENT_IBUF_SIZE (16384 + 325) +#endif + #endif /* ARDUINO_BEARSSL_CONFIG_H_ */ From f494e2c4055d7e0f1b529138bd1c2d6ad5f9bfbf Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Apr 2025 13:54:24 +0200 Subject: [PATCH 37/40] Add ArduinoBearSSL library dependency --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 34b6cae52..08e315f96 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge,stm32 includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient,ArduinoBearSSL From 2966cf72f32caf1df83e8346eda8aab7a070a37f Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 11 Apr 2025 14:05:19 +0200 Subject: [PATCH 38/40] BearSSLCOnfig: disable br_sslio_close --- src/ArduinoBearSSLConfig.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ArduinoBearSSLConfig.h b/src/ArduinoBearSSLConfig.h index 2c8d4ea99..1d340d423 100644 --- a/src/ArduinoBearSSLConfig.h +++ b/src/ArduinoBearSSLConfig.h @@ -36,6 +36,20 @@ /* If uncommented TA should be configured via constructor */ //#define ARDUINO_BEARSSL_DISABLE_BUILTIN_TRUST_ANCHORS +/* If uncommented disables br_sslio_close call.From BearSSL docs: + * + * br_sslio_close(): perform the SSL closure protocol. This entails sending a + * close_notify alert, and receiving a close_notify response. + * + * Note that a number of deployed SSL implementations do not follow the protocol + * for closure, and may drop the underlying socket abruptly. As such, errors are + * often reported by br_sslio_close(). + * + * In case of mbed-os + ArduinoIoTCloud br_sslio_close is endless looping + * blocking sketch execution. + */ +#define ARDUINO_BEARSSL_DISABLE_TLS_CLOSE + #define BEAR_SSL_CLIENT_CHAIN_SIZE 1 #if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) ||\ From 80bf76e1a77b9138b32f4ae93df6a7d386ac7686 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Fri, 11 Apr 2025 16:46:32 +0200 Subject: [PATCH 39/40] Add Arduino_CloudUtils library dependency --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 34b6cae52..9435ba340 100644 --- a/library.properties +++ b/library.properties @@ -8,4 +8,4 @@ category=Communication url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge,stm32 includes=ArduinoIoTCloud.h -depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient +depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient,Arduino_CloudUtils From da9c7760a37101113d3563a7c3058529cc50bc93 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 14 Apr 2025 09:22:08 +0200 Subject: [PATCH 40/40] Release v2.5.0 --- library.properties | 3 +-- src/AIoTC_Config.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index 26f66f372..046c47482 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoIoTCloud -version=2.4.1 +version=2.5.0 author=Arduino maintainer=Arduino sentence=This library allows connecting to the Arduino IoT Cloud service. @@ -9,4 +9,3 @@ url=https://github.com/arduino-libraries/ArduinoIoTCloud architectures=mbed,samd,esp8266,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_opta,mbed_giga,renesas_portenta,renesas_uno,mbed_edge,stm32 includes=ArduinoIoTCloud.h depends=Arduino_ConnectionHandler,Arduino_DebugUtils,Arduino_SecureElement,ArduinoMqttClient,ArduinoECCX08,RTCZero,Adafruit SleepyDog Library,ArduinoHttpClient,Arduino_CloudUtils,ArduinoBearSSL - diff --git a/src/AIoTC_Config.h b/src/AIoTC_Config.h index 4061cdd05..82e5093ef 100644 --- a/src/AIoTC_Config.h +++ b/src/AIoTC_Config.h @@ -178,6 +178,6 @@ #define AIOT_CONFIG_LASTVALUES_SYNC_MAX_RETRY_CNT (10UL) #endif -#define AIOT_CONFIG_LIB_VERSION "2.4.1" +#define AIOT_CONFIG_LIB_VERSION "2.5.0" #endif /* ARDUINO_AIOTC_CONFIG_H_ */